pax_global_header00006660000000000000000000000064131155516250014516gustar00rootroot0000000000000052 comment=bd634c895fedd7ae55fdde111b8539531d235fcd mathicgb-master/000077500000000000000000000000001311555162500141315ustar00rootroot00000000000000mathicgb-master/.gitignore000077500000000000000000000012231311555162500161220ustar00rootroot00000000000000# MathicGB generated files *.gb *.stats *.qmat *.brmat *.rbrmat # Compiled Object files *.slo *.lo *.o *.exe /mgb # Compiled Dynamic libraries *.so # Compiled Static libraries *.lai *.la *.a # Emacs backup files \#*\# *~ # Autotools generated files config.log config.status libtool .deps/ .dirstamp aclocal.m4 autom4te.cache/ Makefile.in Makefile configure .libs/ /build/autotools/compile /build/autotools/mathicgb.pc /build/autotools/test-driver # Visual studio generated files *.suo *.sdf *.opensdf *.vcxproj.user *.psess *.vsp output/ # Configure build targets deb/ debnoass/ pro/ rel/ relass/ /test-suite.log /unittest /unittest.log /unittest.trs mathicgb-master/Makefile.am000077500000000000000000000125201311555162500161700ustar00rootroot00000000000000# options passed to aclocal, which is a tool for making macroes visible to # autoconf. We use -I to tell aclocal where we put the local macros. ACLOCAL_AMFLAGS = -I build/autotools/m4 # Options passed to the C and C++ PreProcessor (CPP) and compiler AM_CPPFLAGS = -I${top_srcdir}/ -I$(top_srcdir)/src/ $(DEPS_CFLAGS) # tell Libtool what the name of the library is. lib_LTLIBRARIES = libmathicgb.la # libraries that are needed by this library libmathicgb_la_LIBADD= $(DEPS_LIBS) # the sources that are built to make libmathicgb. Listing the headers in # sources ensure that those files are included in distributions. libmathicgb_la_SOURCES = src/mathicgb/MonoArena.hpp \ src/mathicgb/Range.hpp src/mathicgb/ReducerPack.hpp \ src/mathicgb/ReducerPack.cpp src/mathicgb/ClassicGBAlg.cpp \ src/mathicgb/ClassicGBAlg.hpp src/mathicgb/MonoLookup.hpp \ src/mathicgb/MonoLookup.cpp src/mathicgb/StaticMonoMap.hpp \ src/mathicgb/SigPolyBasis.cpp src/mathicgb/SigPolyBasis.hpp \ src/mathicgb/Basis.cpp src/mathicgb/Basis.hpp \ src/mathicgb/io-util.cpp src/mathicgb/io-util.hpp \ src/mathicgb/KoszulQueue.hpp src/mathicgb/ModuleMonoSet.cpp \ src/mathicgb/ModuleMonoSet.hpp src/mathicgb/Poly.hpp \ src/mathicgb/PolyBasis.cpp src/mathicgb/PolyBasis.hpp \ src/mathicgb/PolyHashTable.cpp src/mathicgb/PolyHashTable.hpp \ src/mathicgb/PolyRing.cpp src/mathicgb/PolyRing.hpp \ src/mathicgb/Reducer.cpp src/mathicgb/Reducer.hpp \ src/mathicgb/ReducerDedup.hpp src/mathicgb/ReducerDedup.cpp \ src/mathicgb/ReducerHash.hpp src/mathicgb/ReducerHash.cpp \ src/mathicgb/ReducerHashPack.hpp src/mathicgb/ReducerHashPack.cpp \ src/mathicgb/ReducerHelper.hpp src/mathicgb/ReducerNoDedup.hpp \ src/mathicgb/ReducerNoDedup.cpp src/mathicgb/ReducerPackDedup.hpp \ src/mathicgb/ReducerPackDedup.cpp src/mathicgb/SignatureGB.cpp \ src/mathicgb/SignatureGB.hpp src/mathicgb/SigSPairs.cpp \ src/mathicgb/SigSPairs.hpp src/mathicgb/SPairs.cpp \ src/mathicgb/SPairs.hpp src/mathicgb/stdinc.h \ src/mathicgb/SigSPairQueue.hpp src/mathicgb/SigSPairQueue.cpp \ src/mathicgb/SparseMatrix.hpp src/mathicgb/SparseMatrix.cpp \ src/mathicgb/QuadMatrixBuilder.hpp \ src/mathicgb/QuadMatrixBuilder.cpp src/mathicgb/TypicalReducer.cpp \ src/mathicgb/TypicalReducer.hpp src/mathicgb/F4Reducer.hpp \ src/mathicgb/F4Reducer.cpp src/mathicgb/F4MatrixBuilder.hpp \ src/mathicgb/F4MatrixBuilder.cpp src/mathicgb/QuadMatrix.hpp \ src/mathicgb/QuadMatrix.cpp src/mathicgb/F4MatrixReducer.cpp \ src/mathicgb/F4MatrixReducer.hpp src/mathicgb/MonomialMap.hpp \ src/mathicgb/RawVector.hpp src/mathicgb/Atomic.hpp \ src/mathicgb/FixedSizeMonomialMap.hpp src/mathicgb/CFile.hpp \ src/mathicgb/CFile.cpp src/mathicgb/LogDomain.hpp \ src/mathicgb/LogDomain.cpp src/mathicgb/LogDomainSet.hpp \ src/mathicgb/F4MatrixBuilder2.hpp src/mathicgb/F4MatrixBuilder2.cpp \ src/mathicgb/LogDomainSet.cpp src/mathicgb/F4ProtoMatrix.hpp \ src/mathicgb/F4ProtoMatrix.cpp src/mathicgb/F4MatrixProject.hpp \ src/mathicgb/F4MatrixProjection.cpp src/mathicgb/ScopeExit.hpp \ src/mathicgb.cpp src/mathicgb.h src/mathicgb/mtbb.hpp \ src/mathicgb/PrimeField.hpp src/mathicgb/MonoMonoid.hpp \ src/mathicgb/MonoProcessor.hpp src/mathicgb/MonoOrder.hpp \ src/mathicgb/Scanner.hpp src/mathicgb/Scanner.cpp \ src/mathicgb/Unchar.hpp src/mathicgb/MathicIO.hpp \ src/mathicgb/NonCopyable.hpp # The headers that libmathicgb installs. mathicgbA_include_HEADERS = src/mathicgb.h mathicgbA_includedir = $(includedir) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = build/autotools/mathicgb.pc # When making a distribution file, Automake knows to include all files # that are necessary to build the project. EXTRA_DIST specifies files # to include beyond those used in the build process. EXTRA_DIST = autogen.sh dist_man_MANS = doc/mgb.1 bin_PROGRAMS = mgb # set up the console program. Listing the headers in sources ensure that # those files are included in distributions. mgb_SOURCES = src/cli/GBMain.cpp src/cli/CommonParams.hpp \ src/cli/CommonParams.cpp src/cli/GBAction.hpp src/cli/GBAction.cpp \ src/cli/GBCommonParams.hpp src/cli/GBCommonParams.cpp \ src/cli/MatrixAction.cpp src/cli/MatrixAction.hpp \ src/cli/SigGBAction.hpp src/cli/SigGBAction.cpp \ src/cli/HelpAction.hpp src/cli/HelpAction.cpp mgb_LDADD = $(top_builddir)/libmathicgb.la $(DEPS_LIBS) -lmathic -lmemtailor -lpthread # set up tests to run on "make check" if with_gtest TESTS=unittest check_PROGRAMS=$(TESTS) # this prevents g++ 4.8.2 from crashing and churning through memory when compiling under Ubuntu 64 14.04.1 src/test/MonoMonoid.o src/test/Range.o : CXXFLAGS += -O0 unittest_LDADD = $(DEPS_LIBS) $(top_builddir)/libmathicgb.la $(DEPS_LIBS) -lmathic -lmemtailor -lpthread test_LIBS= unittest_SOURCES=src/test/Range.cpp src/test/gtestInclude.cpp \ src/test/testMain.cpp src/test/gb-test.cpp src/test/ideals.cpp \ src/test/poly-test.cpp src/test/ideals.hpp src/test/SparseMatrix.cpp \ src/test/QuadMatrixBuilder.cpp src/test/F4MatrixBuilder.cpp \ src/test/F4MatrixReducer.cpp src/test/mathicgb.cpp \ src/test/PrimeField.cpp src/test/MonoMonoid.cpp src/test/Scanner.cpp \ src/test/MathicIO.cpp else check: @echo @echo "Configure did not locate gtest, so unittests cannot be run." endif mathicgb-master/README.md000077500000000000000000000013421311555162500154130ustar00rootroot00000000000000mathicgb ========= Mathicgb is a program for computing Groebner basis and signature Grobner bases. Mathicgb is based on the fast data structures from [mathic](https://github.com/broune/mathic). The paper "Practical Grobner Basis Computation" describes the algorithms in Mathicgb from a high level. It was presented at ISSAC 2012 and is available at http://arxiv.org/abs/1206.6940 The following copyright and license notice applies to all of the files in mathicgb. Copyright 2012 2013 Bjarke Hammersholt Roune (http://www.broune.com) and Michael Stillman Mathicgb is licensed for use under the terms of GNU General Public License version 2 and under any later version; the option is yours. See the files gpl-*.txt in this directory. mathicgb-master/autogen.sh000077500000000000000000000001221311555162500161250ustar00rootroot00000000000000#!/bin/sh srcdir="`dirname '$0'`" autoreconf --verbose --install --force $srcdir mathicgb-master/build/000077500000000000000000000000001311555162500152305ustar00rootroot00000000000000mathicgb-master/build/autotools/000077500000000000000000000000001311555162500172615ustar00rootroot00000000000000mathicgb-master/build/autotools/.gitignore000077500000000000000000000001501311555162500212500ustar00rootroot00000000000000# Autotools generated files ar-lib config.guess config.sub depcomp install-sh ltmain.sh missing mathicgb-master/build/autotools/m4/000077500000000000000000000000001311555162500176015ustar00rootroot00000000000000mathicgb-master/build/autotools/m4/.gitignore000066400000000000000000000001411311555162500215650ustar00rootroot00000000000000# Autotools generated files libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4 mathicgb-master/build/autotools/m4/ax_cxx_compile_stdcxx_11.m4000077500000000000000000000107631311555162500247550ustar00rootroot00000000000000# ============================================================================ # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html # ============================================================================ # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++11 # standard; if necessary, add switches to CXXFLAGS to enable support. # # The first argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # # The second argument, if specified 'mandatory' or if left unspecified, # indicates that baseline C++11 support is required and that the macro # should error out if no mode with that support is found. If specified # 'optional', then configuration proceeds regardless, after defining # HAVE_CXX11 if and only if a supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 3 m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; typedef check> right_angle_brackets; int a; decltype(a) b; typedef check check_type; check_type c; check_type&& cr = static_cast(c); auto d = a; ]) AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl m4_if([$1], [], [], [$1], [ext], [], [$1], [noext], [], [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], [$2], [optional], [ax_cxx_compile_cxx11_required=false], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl AC_LANG_PUSH([C++])dnl ac_success=no AC_CACHE_CHECK(whether $CXX supports C++11 features by default, ax_cv_cxx_compile_cxx11, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [ax_cv_cxx_compile_cxx11=yes], [ax_cv_cxx_compile_cxx11=no])]) if test x$ax_cv_cxx_compile_cxx11 = xyes; then ac_success=yes fi m4_if([$1], [noext], [], [dnl if test x$ac_success = xno; then for switch in -std=gnu++11 -std=gnu++0x; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, $cachevar, [ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXXFLAGS="$ac_save_CXXFLAGS"]) if eval test x\$$cachevar = xyes; then CXXFLAGS="$CXXFLAGS $switch" ac_success=yes break fi done fi]) m4_if([$1], [ext], [], [dnl if test x$ac_success = xno; then for switch in -std=c++11 -std=c++0x; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, $cachevar, [ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXXFLAGS="$ac_save_CXXFLAGS"]) if eval test x\$$cachevar = xyes; then CXXFLAGS="$CXXFLAGS $switch" ac_success=yes break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx11_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) fi else if test x$ac_success = xno; then HAVE_CXX11=0 AC_MSG_NOTICE([No compiler with C++11 support was found]) else HAVE_CXX11=1 AC_DEFINE(HAVE_CXX11,1, [define if the compiler supports basic C++11 syntax]) fi AC_SUBST(HAVE_CXX11) fi ]) mathicgb-master/build/autotools/mathicgb.pc.in000077500000000000000000000004561311555162500220000ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: mathicgb Description: C++ library for Groebner basis computation URL: https://github.com/broune/mathicgb Requires: memtailor mathic Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lmathicgb Cflags: -I${includedir}/ mathicgb-master/build/setup/000077500000000000000000000000001311555162500163705ustar00rootroot00000000000000mathicgb-master/build/setup/make-Makefile.sh000077500000000000000000000166241311555162500213700ustar00rootroot00000000000000#!/usr/bin/env bash mildWarn="" #-Wall -Wextra" ############################################# ################## projects ################# ############################################# # memtailor memtailorIndex=${#projectsName[@]} projectsName+=("memtailor"); projectsGitUrl+=("https://github.com/broune/memtailor.git"); projectsDependencies+=(""); # mathic mathicIndex=${#projectsName[@]} projectsName+=("mathic"); projectsGitUrl+=("https://github.com/broune/mathic.git"); projectsDependencies+=("memtailor"); # mathicgb mathicgbIndex=${#projectsName[@]} projectsName+=("mathicgb"); projectsGitUrl+=("https://github.com/broune/mathicgb.git"); projectsDependencies+=("memtailor mathic"); ############################################# ################## targets ################## ############################################# # release relIndex=${#targetsName[@]}; targetsName+=("rel"); targetsDescription+=("Release build. Optimized, no debug symbols, no asserts."); targetsCPPFLAGS+=("-O2"); targetsCXXFLAGS+=(""); targetsLDFLAGS+=(""); targetsMakeArgs+=(""); targetsDefault+=("yes"); # optimized with asserts relassIndex=${#targetsName[@]}; targetsName+=("relass"); targetsDescription+=("Optimized build with asserts. No debug symbols."); targetsCPPFLAGS+=("-O2 -DMEMTAILOR_DEBUG -DMATHIC_DEBUG -DMATHICGB_DEBUG $mildWarn"); targetsCXXFLAGS+=(""); targetsLDFLAGS+=(""); targetsMakeArgs+=(""); targetsDefault+=("yes"); # debug with asserts debIndex=${#targetsName[@]}; targetsName+=("deb"); targetsDescription+=("Debug build with asserts. Not optimized."); targetsCPPFLAGS+=("-g -DMEMTAILOR_DEBUG -DMATHIC_DEBUG -DMATHICGB_DEBUG $mildWarn"); targetsCXXFLAGS+=(""); targetsLDFLAGS+=(""); targetsMakeArgs+=(""); targetsDefault+=("yes"); #debug without asserts debnoassIndex=${#targetsName[@]}; targetsName+=("debnoass"); targetsDescription+=("Debug build without asserts. Not optimized."); targetsCPPFLAGS+=("-g $mildWarn"); targetsCXXFLAGS+=(""); targetsLDFLAGS+=(""); targetsMakeArgs+=(""); targetsDefault+=("no"); # profile proIndex=${#targetsName[@]}; targetsName+=("pro"); targetsDescription+=("Profile build with optimization and no asserts."); targetsCPPFLAGS+=("-g -pg -O2 $mildWarn"); targetsCXXFLAGS+=(""); targetsLDFLAGS+=("-pg"); targetsMakeArgs+=(""); targetsDefault+=("no"); # profile with asserts proassIndex=${#targetsName[@]}; targetsName+=("proass"); targetsDescription+=("Profile build with optimization and asserts."); targetsCPPFLAGS+=("-g -pg -O2 -DMEMTAILOR_DEBUG -DMATHIC_DEBUG -DMATHICGB_DEBUG $mildWarn"); targetsCXXFLAGS+=(""); targetsLDFLAGS+=("-pg"); targetsMakeArgs+=(""); targetsDefault+=("no"); # analyze build: a larger amount of warnings turned on anaIndex=${#targetsName[@]}; targetsName+=("ana"); targetsDescription+=("Build with many warnings turned on and -Werror."); targetsCPPFLAGS+=("-Wall -Wextra -Wno-uninitialized -Wno-unused-parameter\ -O1 -Wfloat-equal -Wundef\ -Wno-endif-labels -Wshadow -Wlarger-than-1000 -Wpointer-arith \ -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wsign-compare \ -Waggregate-return -Wmissing-noreturn -Wmissing-format-attribute \ -Wno-multichar -Wno-deprecated-declarations -Wpacked \ -Wno-redundant-decls -Wunreachable-code -Winline \ -Wno-invalid-offsetof -Winvalid-pch -Wlong-long \ -Wdisabled-optimization -DMEMTAILOR_DEBUG -DMATHIC_DEBUG -DMATHICGB_DEBUG \ -Werror"); targetsCXXFLAGS+=(""); targetsLDFLAGS+=(""); targetsMakeArgs+=(""); targetsDefault+=("no"); function makeHelpComment { echo "# This file was auto-generated using the script " echo "# mathicgb/build/setup/make-Makefile.sh"; echo "# As such it is recommended to change that script instead of " echo "# changing this file if you want to keep the changes in future." echo "#"; echo "# The projects that you can build are" for ((i=0; i<${#projectsName[@]}; i++)); do echo "#"; echo "# Project: ${projectsName[i]}."; echo "# gitUrl=${projectsGitUrl[i]}"; echo "# dependencies=${projectsDependencies[i]}"; done echo "#"; echo "# Within each project the targets than you can build are"; for ((i=0; i<${#targetsName[@]}; i++)); do echo "#"; echo "# Target: ${targetsName[i]}. ${targetsDescription[i]}"; echo "# CPPFLAGS=${targetsCPPFLAGS[i]}"; echo "# CXXFLAGS=${targetsCXXFLAGS[i]}"; echo "# LDFLAGS=${targetsLDFLAGS[i]}"; echo "# makeArgs=${targetsMakeArgs[i]}"; echo "# buildsByDefault=${targetsDefault[i]}"; done echo "#"; echo "# To build everything that builds by default, type \"make\"."; echo "# (\"make\" will take quite a while to run.)"; echo "# To build all rel targets, type \"make rel\"."; echo "# To build target rel of mathic, type \"make mathicrel\"."; echo "# This will automatically build memtailorrel too due to the"; echo "# dependency."; echo; } function makeTarget { projectIndex="$1"; projectName="${projectsName[projectIndex]}"; projectDependencies="${projectsDependencies[projectIndex]}"; targetIndex="$2"; targetName="${targetsName[targetIndex]}"; targetCPPFLAGS="${targetsCPPFLAGS[targetIndex]}"; targetCXXFLAGS="${targetsCXXFLAGS[targetIndex]}"; targetLDFLAGS="${targetsLDFLAGS[targetIndex]}"; targetMakeArgs="${targetsMakeArgs[targetIndex]}"; targetDefault="${targetsDefault[targetIndex]}"; dependencies=""; for depProject in $projectDependencies; do dependencies+=" $depProject$targetName"; done name="$projectName$targetName" targetDir="$projectName/$targetName"; prefix="\${PWD}/installed/$targetName"; projectConfigureArgs="--prefix=\"$prefix\" \${${projectName}_conf}"; echo "$name: ${projectName}BasicSetup $dependencies" echo $'\t'"rm -rf \"$targetDir\"" echo $'\t'"mkdir -p \"$targetDir\" \"$prefix/lib/pkgconfig\";" echo $'\t'"( \\" echo $'\t'" cd \"$targetDir\"; \\" echo $'\t'" export PKG_CONFIG_PATH=\"$prefix/lib/pkgconfig\"; \\"; echo $'\t'" export CXXFLAGS=\"$targetCXXFLAGS\"; \\"; echo $'\t'" export CPPFLAGS=\"$targetCPPFLAGS\"; \\"; echo $'\t'" export LDFLAGS=\"$targetLDFLAGS\"; \\"; echo $'\t'" export GTEST_PATH=\"../..\"; \\"; echo $'\t'" ../configure $projectConfigureArgs; \\" echo $'\t'" make $targetMakeArgs install; \\" echo $'\t'");" echo "$targetName: $name"; if [ "$targetDefault" = "yes" ]; then echo "$projectName: $name"; fi } function makeGTest { version="1.6.0"; zipFile="gtest-$version.zip"; url="http://googletest.googlecode.com/files/$zipFile"; extractDir="gtest-$version/"; echo "gtest:"; echo $'\t'"rm -rf $zipFile"; echo $'\t'"wget $url;"; echo $'\t'"unzip $zipFile;"; echo $'\t'"rm $zipFile;"; echo $'\t'"rm -rf gtest;"; echo $'\t'"mv $extractDir/ gtest;"; } function makeProject { projectIndex="$1"; name="${projectsName[projectIndex]}"; gitUrl="${projectsGitUrl[projectIndex]}"; dep="$3"; echo "all: $name"; echo "${name}BasicSetup: gtest" echo $'\t'"if [ ! -e \"$name/\" ]; then git clone $gitUrl; fi;" echo $'\t'"if [ ! -e \"$name/configure\" ]; then (cd $name/; ./autogen.sh;); fi;" for ((k=0; k<${#targetsName[@]}; k++)); do makeTarget "$projectIndex" "$k"; done } function makeMakefile { echo "all:"; makeHelpComment; makeGTest; # -j8: Causes 8 parallel tasks including within called makefiles. User # setting overwrites this if the user has specified -jX on the command line. # # V=0: Causes a non-verbose build. echo "MAKEFLAGS += -j8 V=0" for ((j=0; j<${#projectsName[@]}; j++)); do makeProject "$j"; done } makeMakefile mathicgb-master/build/vs12/000077500000000000000000000000001311555162500160235ustar00rootroot00000000000000mathicgb-master/build/vs12/mathicgb-exe/000077500000000000000000000000001311555162500203605ustar00rootroot00000000000000mathicgb-master/build/vs12/mathicgb-exe/mathicgb-exe.vcxproj000077500000000000000000000711051311555162500243410ustar00rootroot00000000000000 Debug-NoAssert Win32 Debug-NoAssert x64 Debug Win32 Debug x64 Release-Assert Win32 Release-Assert x64 Release Win32 Release x64 WarningAsError Win32 WarningAsError x64 {bebd36f1-a124-4c01-8e67-3208d4472661} {534c44f8-ba0a-4af0-95f1-260ca8ef3551} {0928155f-aee7-4b28-ad10-ff7d6488d232} {1CCEB690-2F15-4D60-AF28-2F0AC260E685} Win32Proj mathicgbexe Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application false v110 true Unicode Application false v110 true Unicode Application false v110 false Unicode Application false v110 false Unicode true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mgb NotUsing Level3 Disabled WIN32;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN64;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN32;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false true /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN64;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false true /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 NotUsing MaxSpeed true true WIN32;NDEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 NotUsing MaxSpeed true true WIN64;NDEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) false Level3 NotUsing MaxSpeed true true WIN32;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDebugDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 NotUsing MaxSpeed true true WIN64;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDebugDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) mathicgb-master/build/vs12/mathicgb-exe/mathicgb-exe.vcxproj.filters000077500000000000000000000045211311555162500260060ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files mathicgb-master/build/vs12/mathicgb-lib/000077500000000000000000000000001311555162500203455ustar00rootroot00000000000000mathicgb-master/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj000077500000000000000000001010771311555162500243150ustar00rootroot00000000000000 Debug-NoAssert Win32 Debug-NoAssert x64 Debug Win32 Debug x64 Release-Assert Win32 Release-Assert x64 Release Win32 Release x64 WarningAsError Win32 WarningAsError x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232} Win32Proj mathicgblib StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary true v110 Unicode StaticLibrary false v110 true Unicode StaticLibrary false v110 true Unicode StaticLibrary false v110 false Unicode StaticLibrary false v110 false Unicode true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathicgb .lib Level3 Disabled TBB_USE_DEBUG=1;WIN32;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Windows true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib NotUsing Level3 Disabled TBB_USE_DEBUG=1;WIN64;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Windows true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib Level3 Disabled TBB_USE_DEBUG=1;WIN32;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true true false false /bigobj %(AdditionalOptions) Windows true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib NotUsing Level3 Disabled TBB_USE_DEBUG=1;WIN64;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true true false false /bigobj %(AdditionalOptions) Windows true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib Level3 Disabled TBB_USE_DEBUG=1;WIN32;NDEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Windows true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib NotUsing Level3 Disabled TBB_USE_DEBUG=1;WIN64;NDEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Windows true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib Level3 NotUsing MaxSpeed true true WIN32;NDEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDLL /bigobj %(AdditionalOptions) Windows true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) tbb.lib Level3 NotUsing MaxSpeed true true WIN64;NDEBUG;_WINDOWS;_USRDLL;MATHICGBLIB_EXPORTS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDLL /bigobj %(AdditionalOptions) Windows true true true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) tbb.lib Level3 NotUsing MaxSpeed true true TBB_USE_DEBUG=1;WIN32;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDebugDLL /bigobj %(AdditionalOptions) Windows true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib Level3 NotUsing MaxSpeed true true TBB_USE_DEBUG=1;WIN64;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDebugDLL stdinc.h /bigobj %(AdditionalOptions) Windows true true true $(ProjectDir)\..\..\..\..\tbb\lib\intel64\vc11;%(AdditionalLibraryDirectories) tbb_debug.lib mathicgb-master/build/vs12/mathicgb-lib/mathicgb-lib.vcxproj.filters000077500000000000000000000260201311555162500257560ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files mathicgb-master/build/vs12/mathicgb-test/000077500000000000000000000000001311555162500205565ustar00rootroot00000000000000mathicgb-master/build/vs12/mathicgb-test/mathicgb-test.vcxproj000077500000000000000000000722201311555162500247340ustar00rootroot00000000000000 Debug-NoAssert Win32 Debug-NoAssert x64 Debug Win32 Debug x64 Release-Assert Win32 Release-Assert x64 Release Win32 Release x64 WarningAsError Win32 WarningAsError x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF} Win32Proj mathicgbtest Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application true v110 Unicode Application false v110 true Unicode Application false v110 true Unicode Application false v110 false Unicode Application false v110 false Unicode true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ true $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ mathic-test false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ false $(SolutionDir)\output\$(Platform)\$(Configuration)\ $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ NotUsing Level3 Disabled WIN32;_VARIADIC_MAX=10;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN64;_VARIADIC_MAX=10;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN32;_VARIADIC_MAX=10;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false true /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN64;_VARIADIC_MAX=10;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false true /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN32;_VARIADIC_MAX=10;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) NotUsing Level3 Disabled WIN64;_VARIADIC_MAX=10;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false false /bigobj %(AdditionalOptions) Console true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 NotUsing MaxSpeed true true WIN32;_VARIADIC_MAX=10;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 NotUsing MaxSpeed true true WIN64;_VARIADIC_MAX=10;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 NotUsing MaxSpeed true true WIN32;_VARIADIC_MAX=10;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDebugDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Level3 NotUsing MaxSpeed true true WIN64;_VARIADIC_MAX=10;MATHICGB_DEBUG;MATHIC_DEBUG;MEMTAILOR_DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(ProjectDir)\..\..\..\..\tbb\include;$(ProjectDir)\..\..\..\..\gtest\include;$(ProjectDir)\..\..\..\..\gtest;$(ProjectDir)\..\..\..\..\mathicgb\src;$(ProjectDir)\..\..\..\..\mathic\src;$(ProjectDir)\..\..\..\..\memtailor\src;%(AdditionalIncludeDirectories) true false MultiThreadedDebugDLL /bigobj %(AdditionalOptions) Console true true true $(ProjectDir)\..\..\..\..\tbb\lib\ia32\vc11;%(AdditionalLibraryDirectories) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) {bebd36f1-a124-4c01-8e67-3208d4472661} {534c44f8-ba0a-4af0-95f1-260ca8ef3551} {0928155f-aee7-4b28-ad10-ff7d6488d232} mathicgb-master/build/vs12/mathicgb-test/mathicgb-test.vcxproj.filters000077500000000000000000000052501311555162500264020ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files mathicgb-master/build/vs12/mathicgb.sln000077500000000000000000000252321311555162500203260ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathicgb-exe", "mathicgb-exe\mathicgb-exe.vcxproj", "{1CCEB690-2F15-4D60-AF28-2F0AC260E685}" ProjectSection(ProjectDependencies) = postProject {0928155F-AEE7-4B28-AD10-FF7D6488D232} = {0928155F-AEE7-4B28-AD10-FF7D6488D232} {BEBD36F1-A124-4C01-8E67-3208D4472661} = {BEBD36F1-A124-4C01-8E67-3208D4472661} {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} = {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathicgb-test", "mathicgb-test\mathicgb-test.vcxproj", "{A2CAAD29-5CF3-4B89-9811-8951359B8AAF}" ProjectSection(ProjectDependencies) = postProject {0928155F-AEE7-4B28-AD10-FF7D6488D232} = {0928155F-AEE7-4B28-AD10-FF7D6488D232} {BEBD36F1-A124-4C01-8E67-3208D4472661} = {BEBD36F1-A124-4C01-8E67-3208D4472661} {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} = {534C44F8-BA0A-4AF0-95F1-260CA8EF3551} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathicgb-lib", "mathicgb-lib\mathicgb-lib.vcxproj", "{0928155F-AEE7-4B28-AD10-FF7D6488D232}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memtailor-lib", "..\..\..\memtailor\build\vs12\memtailor-lib\memtailor-lib.vcxproj", "{534C44F8-BA0A-4AF0-95F1-260CA8EF3551}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mathic-lib", "..\..\..\mathic\build\vs12\mathic-lib\mathic-lib.vcxproj", "{BEBD36F1-A124-4C01-8E67-3208D4472661}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Debug-NoAssert|Win32 = Debug-NoAssert|Win32 Debug-NoAssert|x64 = Debug-NoAssert|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 Release-Assert|Win32 = Release-Assert|Win32 Release-Assert|x64 = Release-Assert|x64 WarningAsError|Win32 = WarningAsError|Win32 WarningAsError|x64 = WarningAsError|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug|Win32.ActiveCfg = Debug|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug|Win32.Build.0 = Debug|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug|x64.ActiveCfg = Debug|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug|x64.Build.0 = Debug|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release|Win32.ActiveCfg = Release|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release|Win32.Build.0 = Release|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release|x64.ActiveCfg = Release|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release|x64.Build.0 = Release|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release-Assert|Win32.Build.0 = Release-Assert|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release-Assert|x64.ActiveCfg = Release-Assert|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.Release-Assert|x64.Build.0 = Release-Assert|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.WarningAsError|Win32.Build.0 = WarningAsError|Win32 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.WarningAsError|x64.ActiveCfg = WarningAsError|x64 {1CCEB690-2F15-4D60-AF28-2F0AC260E685}.WarningAsError|x64.Build.0 = WarningAsError|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug|Win32.ActiveCfg = Debug|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug|Win32.Build.0 = Debug|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug|x64.ActiveCfg = Debug|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug|x64.Build.0 = Debug|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release|Win32.ActiveCfg = Release|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release|Win32.Build.0 = Release|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release|x64.ActiveCfg = Release|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release|x64.Build.0 = Release|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release-Assert|Win32.Build.0 = Release-Assert|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release-Assert|x64.ActiveCfg = Release-Assert|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.Release-Assert|x64.Build.0 = Release-Assert|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.WarningAsError|Win32.Build.0 = WarningAsError|Win32 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.WarningAsError|x64.ActiveCfg = WarningAsError|x64 {A2CAAD29-5CF3-4B89-9811-8951359B8AAF}.WarningAsError|x64.Build.0 = WarningAsError|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug|Win32.ActiveCfg = Debug|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug|Win32.Build.0 = Debug|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug|x64.ActiveCfg = Debug|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug|x64.Build.0 = Debug|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release|Win32.ActiveCfg = Release|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release|Win32.Build.0 = Release|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release|x64.ActiveCfg = Release|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release|x64.Build.0 = Release|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release-Assert|Win32.Build.0 = Release-Assert|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release-Assert|x64.ActiveCfg = Release-Assert|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.Release-Assert|x64.Build.0 = Release-Assert|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.WarningAsError|Win32.Build.0 = WarningAsError|Win32 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.WarningAsError|x64.ActiveCfg = WarningAsError|x64 {0928155F-AEE7-4B28-AD10-FF7D6488D232}.WarningAsError|x64.Build.0 = WarningAsError|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|Win32.ActiveCfg = Debug|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|Win32.Build.0 = Debug|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|x64.ActiveCfg = Debug|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug|x64.Build.0 = Debug|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|Win32.ActiveCfg = Release|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|Win32.Build.0 = Release|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|x64.ActiveCfg = Release|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release|x64.Build.0 = Release|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|Win32.Build.0 = Release-Assert|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|x64.ActiveCfg = Release-Assert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.Release-Assert|x64.Build.0 = Release-Assert|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|Win32.Build.0 = WarningAsError|Win32 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|x64.ActiveCfg = WarningAsError|x64 {534C44F8-BA0A-4AF0-95F1-260CA8EF3551}.WarningAsError|x64.Build.0 = WarningAsError|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|Win32.ActiveCfg = Debug|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|Win32.Build.0 = Debug|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|x64.ActiveCfg = Debug|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug|x64.Build.0 = Debug|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|Win32.ActiveCfg = Debug-NoAssert|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|Win32.Build.0 = Debug-NoAssert|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|x64.ActiveCfg = Debug-NoAssert|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Debug-NoAssert|x64.Build.0 = Debug-NoAssert|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|Win32.ActiveCfg = Release|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|Win32.Build.0 = Release|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|x64.ActiveCfg = Release|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release|x64.Build.0 = Release|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|Win32.ActiveCfg = Release-Assert|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|Win32.Build.0 = Release-Assert|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|x64.ActiveCfg = Release-Assert|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.Release-Assert|x64.Build.0 = Release-Assert|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|Win32.ActiveCfg = WarningAsError|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|Win32.Build.0 = WarningAsError|Win32 {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|x64.ActiveCfg = WarningAsError|x64 {BEBD36F1-A124-4C01-8E67-3208D4472661}.WarningAsError|x64.Build.0 = WarningAsError|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal mathicgb-master/build/vs12/notes.txt000077500000000000000000000355571311555162500177360ustar00rootroot00000000000000<<<<< Notes on steps when setting up a new Visual Studio project >>>>> I did this with Visual Studio Professional 2012. I am noting the changes I had to do to get a project that works the way I want it to. You may want something else so it is not guaranteed that you can use this for anything. * Create an empty solution Close anything you have open in Visual Studio first. In the FILE menu, select "new" and then "project". Under "Other Project Types" select "Visual Studio Solutions". Your only option will now be "Blank Solution". Fill out the name of the solution and the path where it should go and click "OK". You now have a solution with no projects in it in a subdirectory with the same name as the solution. If you want the solution to not be in a directory named after the project, close the solution in Visual Studio and move the files in the directory to where you want them to go. You can now open those files in the new location with no issues. Once you add files with relative paths probably this step will be much more cumbersome, so do it now if you want to do it at all. * Create new projects inside your solution Right-click your solution in the Solution Explorer and click "Add" and then "New Project". Select the kind of project you want, name the project and click "OK". On the next window click "Next". You now have several options. I don't want to use any of the autogenerated stuff that Visual Studio will add to the project, so I select "Empty project" and deselect all other options. Then click "Finish". You will now have a project file in a subdirectory of the directory that the solution is in. The name of the directory is the same as the name of the project. * Add existing projects to your solution If the existing project you are adding has solution names or platforms that you wish to also add to your new projects, do not add the existing project to your solution until you have added all the solutions and platforms that you want to add to your new projects. Otherwise, as far as I can determine, you will not be able to add those configurations and platforms to the existing project without manually editing the project files with a text editor - Visual Studio will tell you that the platform and configuration is already in use. See http://www.dpvreony.co.uk/blog/post/v/62. If you add something by mistake, you can remove it, then delete the now unused configurations and platforms, create the platforms and configurations you want and then re-add the existing project. I suspect you can also do this by creating a new solution only for setting up a new project, then delete the new solution and just include the new project into the old solution. I feel like there must be a more reasonable way to handle this, though, but I don't know about it. You may have existing projects that you want to add to your solution. For example if you have a project that generates a DLL that is needed by another project in your current solution, you may want to add that DLL-producing project to your solution. This is especially true if you forsee simultaneously making changes to both the EXE project and the DLL project, since this way Visual Studio will take care of tracking the dependencies (see how to set up project references below). Right-click your solution in the Solution Explorer and click "Add" and then "Existing Project". Find the project you want to add click "Open". The existing project is now in your solution. The path to the project is relative, so if you move the solution or the project you either have to move them so the relative path is the same or you have to remove the project and re-add it. * Add source files Right click the project in the Solution Explorer and select "add" and then "existing item". Then you get a dialog to select the files you want to add to the project. You should select both the header files and the implementation files. These are included using relative paths, so you can move things around as long as the relative path between the project file and the source files remains the same. If you are making a DLL project and there is an implementation file that defines main(), remember not to include it in your DLL project. * Properties Right click the project in the Solution Explorer and select "Properties". Remember that you need to set all the properties for every configuration of every project. You can select "All Configurations" in the upper left where it says "Configuration:" to make your changes take effect for all the configurations of the project. Remember to select a specific configuration for changes that are specific to that configurationt. If you have more than 2 configurations then you can also select a subset of configurations by choosing "multiple configurations" instead of "all configurations". You can also set a setting across several projects by opening the property page for one project and then shift-left-clicking other projects to select more than one at a time - any changes will apply to all the selected projects. ** Configuration Properties *** General -Output Directory = $(SolutionDir)\output\$(Platform)\$(Configuration)\ -Intermediate Directory = $(SolutionDir)\output\$(Platform)\$(Configuration)\intermediate\$(MSBuildProjectName)\ -Target Name = output file name without extension, for example "memtailor" -Target Extension = ensure this is what you want -Configuration Type = ensure this is what you want *** C/C++ **** General -Additional Include Directories = set these up if you need them Remember to use relative paths, not absolute! -Multi-processor Compilation = set to yes **** Proprocessor -Preprocessor Definitions = ensure this is what you want. For builds with asserts on/off, define macroes that turn asserts on/off. **** Code Generation -Enable Minimal Rebuild = set to no It is required to disable this setting to enable multi-processor building. I've found multiprocessor building to be more useful, but you may not like it in which case you should set these settings the other way around. **** Language -Open MP Support = change if you need it **** Precompiled Headers -Set these fields up if you want to use precompiled headers. *** Linker You will only have this tab if you are building a .exe file. Libraries instead have a tab called "librarian". **** General -Additional Library Directories = extra places to look for .dll and .lib files. **** Input -Additional Dependencies = put in the names of libraries that you want to link in, including the .lib or .dll extension. You do not need to specify the outputs of other projects in the same solution - these are handled using project references. * Project References Select your project, click the Project menu and select References. Add references to any other projects whose output DLL or LIB file you want to use in the output for this project. This automatically also sets up project dependencies so you do not need to do that. * Start-up project right-click the project in the Solution Explorer and select "set as start-up project". This simply means that this project will be the one that is selected by default when you open the solution. <<<<< Extra configurations >>>>> * Release-Assert You want a version with asserts enabled that is still optimized. That way you do not have to sit and wait for a very slow non-optimized debug executable to run with asserts on in the common case that none of the asserts trigger and all the test pass or if you can see what the problem is from the assert without needing to go into the debugger. If you get an assert or test failure that you need to go into the debugger for, simply select the debug configuration and run the program again. ** Make the new configuration If some existing project already uses the configuration you want to make, then it will already exist in your solution. *** If the configuration does not exist in your solution Select the configuration drop-down from the top of the screen and select "new" Set it to copy settings from the Release build configuration. Mark the "create new project configurations" tick-box. If you do not see "new" on the configuration drop-down (I don't know why it disappears sometimes), instead select Configuration Manager and select new from the drop-down in the upper left corner. This will create the new configuration across all your projects in the solution. If you only want a configuration to be available for a single project, instead select the configuration drop-down for that project in the middle part of the Configuration Manager. *** If the configuration already exists in your solution Go into the Configuration Manager, find the project you want to add the existing configuration to, right-click the drop-down in the Configuration column and click "New". After that things are the same as above, except you need to do this for each project. ** Fix settings Go into Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions. Now select the Release configuration, copy the preprocessor settings from there (ctrl-v), go back to Release-Assert and paste (ctrl-c) the debug preprocessor settings there. You also need to go to C/C++ -> Code Generation and set Runtime Library to a debug setting - select whatever is selected for your Debug configuration. If your project links in external libraries you might need to select a debug version of those libraries too - do whatever you debug configuration does. If you can get away with not using external debug libraries that might be good since possibly they have been built with optimization turned off in which case they will be slow. If you have more than one project you need to fix the settings for each project. If you get mysterious errors about missing linker symbols or incompatible libraries then possibly that is because you forgot to do the above for one of your projects that is being depended upon by one of the other projects that you did remember to do this for. * Debug-NoAssert Sometimes you are debugging an issue that is not an assertion failure. In that case you may need to run some significant computation for a while until you get to the issue, such as a segmentation fault. To debug you have to compile without optimization, so this can be very slow and it will be even worse if you also have asserts turned on. So it is good to have a build that you can debug but where asserts are not turned on. To realize this, duplicate the debug build as above and defined NDEBUG or, alternatively, do not define whatever preprocessor macroes you've got that turn assertions on. You do this in C/C++ -> Preprocessor -> Preprocessor Definitions. * WarningAsError If you want to have no warnings in your build you'll want to set use the setting "treat warnings as errors". Unfortunately, if your code has many warnings, you probably want your code to still be compilable even though you have not fixed all the warnings yet. When needing to meet a deadline, you might let some warnings stand until a few days later. To avoid having to go through all your projects and turn "treat warnings as errors" on and off, you can make a new project that has this setting permanently turned on. Really you should have one with asserts and one without, though I just make a single one with asserts on. So I duplicate the Debug build and go into C/C++ -> General -> Treat Warnings as Errors and set it to "yes" for each project. <<<<< Specific instructions for gtest >>>>> I had to define the preprocessor macro "_VARIADIC_MAX=10" to build gtest in MSVC. This step should become unnecessary in future once MSVC supports variadic templates. To enable test files to include gtest.h, add an additional relative include path to gtest/include/. I've found the easiest thing to get gtest building is to just include the file at gtest/src/gtest-all.cc from a file in my own test project. This requires an addtional relative include path for gtest/ since that file includes all the other .cc files using a path relative to the base directory of gtest. This way you do not have to deal with outdated external Visual Studio project files or project files that do not have the compiler flags that you need and then you have to edit them anyway even if they are up to date. <<<<< Setting up 64 bit compilation >>>>> The default setting is to compile in 32 bit mode, so unless you changed that you have now got a 32 bit project. One of the problems with this is that you now can use no more than 2-3 GB of ram before getting an allocation failure, even if your computer has much more free RAM than that. If you included an existing project with a 64 bit platform build then that option will already exist in your solution. * If you do not have a 64 bit mode yet At the top of your screen it will say "Win32". It is the third drop-down in the middle if you did not move your toolbars. Click it and select "Configuration Manager". At the right it says "Active solution platform" and then "Win32". Click the drop-down that says "Win32" and select "". Where it says "Type or select the new platform", select x64 and make sure "create new project platforms" is selected. That's it, you can now select a 64 bit mode by choosing between x86 and x64 in the drop-down at the top. * If you have a 64 bit mode already I don't know that you can do this directly then. The best work-around I've found is to remove the projects that already have 64 bit from the solution, then delete 64 bit, re-create it and then add the removed projects back into the solution. * Fixing settings Visual Studio may or may not have done this for you already. I suspect it does this if and only if you have not altered the preprocessor defines from the default values: - change the preprocessor define WIN32 to WIN64. <<<<< Comitting files to version tracking system >>>>> You want to include these files for version tracking: .vcxproj: Stores a MSVC project .sln: Stores a MSVC solution, which contains references to a set of projects .vcxproj.filters: Specifies for example that .h files go in the Header Files node These files are safe to delete (after you close the project/solution) and do not need to be tracked: .suo: local settings, such as what windows you've got open .sdf: browsing database of what is defined where - is autogenerated form the source .opensdf: should only exist while a project/solution is open. output/: if you did what it says above, this is output files intermediate/: if you did what it says above, this is intermediate files This file I'm not sure about .vcxproj.user: supposedly only relevant to converting old MSVC projects, but I am still getting it generated every time I open a new project. For that reason I assume that this does not need to be tracked. mathicgb-master/configure.ac000077500000000000000000000166541311555162500164360ustar00rootroot00000000000000dnl AC_INIT sets up autoconf and must be first macro. AC_INIT([mathicgb], [1.0]) # package, version, bug-report-email # set up information about directories AC_CONFIG_MACRO_DIR([build/autotools/m4]) # directory of extra autoconf macroes AC_CONFIG_AUX_DIR([build/autotools]) # directory for auxiliary build tools (install-sh etc) # check that source directory is correct dnl if autoconf is told the source code is in a directory that does not dnl contain this file then it knows that the directory is wrong. AC_CONFIG_SRCDIR([src/mathicgb.h]) # Check availability and location of dependencies # PKG_CHECK_MODULES([MEMTAILOR], [memtailor]) # PKG_CHECK_MODULES([MATHIC], [mathic]) # Locate the C++ compiler. AC_PROG_CXX AC_LANG([C++]) # Require C++11 support AX_CXX_COMPILE_STDCXX_11(, [mandatory]) AM_PROG_AR dnl ----- The gtest dependency AC_ARG_WITH([gtest], AS_HELP_STRING( [--with-gtest], [use gtest, which is required for running the unit tests with make check. Per the recommendation of the gtest documentation, gtest is compiled with the tests, so an installed gtest is not usable - you need the gtest source. GTEST_PATH indicates where to look for gtest and it is also where gtest will be downloaded to if not found. The default path is srcdir/libs so that gtest needs to be at srcdir/libs/gtest/ where srcdir is the base of the directory being configured from.] )) AC_MSG_CHECKING([for gtest]) AS_IF([test "x$GTEST_PATH" == "x"], [GTEST_PATH="$srcdir/libs"]) AS_IF([test "x$GTEST_VERSION" == "x"], [GTEST_VERSION="1.6.0"]) AS_IF([test "x$with_gtest" == "x"], [with_gtest="download"]) AS_IF([test "x$with_gtest" == "xdownload"], [with_gtest="yes"; AC_CHECK_FILE([$GTEST_PATH/src/gtest-all.cc], [], [ echo "downloading of gtest disabled" >&2; exit 1 mkdir -p "$GTEST_PATH"; ( cd $GTEST_PATH; rm -rf gtest-$GTEST_VERSION.zip wget http://googletest.googlecode.com/files/gtest-$GTEST_VERSION.zip; unzip gtest-$GTEST_VERSION.zip; rm gtest-$GTEST_VERSION.zip rm -rf gtest/ mv gtest-$GTEST_VERSION/ gtest/ ); if test ! -e "$GTEST_PATH/src/gtest-all.cc"; then AC_MSG_WARN([Failed to download or extract gtest.]); with_gtest="no"; else with_gtest="yes"; fi ])], [test "x$with_gtest" == "xyes"], [ AC_CHECK_FILE([$GTEST_PATH/src/gtest-all.cc], [], [ AC_MSG_ERROR([could not find gtest source at path $GTEST_PATH.]) ]) ], [test "x$with_gtest" == "xno"], [], [AC_MSG_ERROR([invalid value $with_gtest for with_gtest.])] ) AS_IF([test "x$with_gtest" == "xyes"], [GTEST_CFLAGS="-I$GTEST_PATH/include -I$GTEST_PATH"]); AM_CONDITIONAL(with_gtest, test "x$with_gtest" == "xyes") dnl ----- The TBB dependency AC_ARG_WITH([tbb], AS_HELP_STRING( [--with-tbb], [use TBB, which is required for multithreading. The value detect, which is the default, enables TBB if it can be found and otherwise prints a warning and continues the build without multithreading support. TBB is not available for Cygwin (last checked March 2013).] )) AS_IF([test "x$with_tbb" == "x"], [with_tbb="detect"]) AS_IF( [test "x$with_tbb" == "xdetect"], [PKG_CHECK_MODULES([TBB], [tbb], [with_tbb="yes"], [with_tbb="no"; AC_MSG_WARN([TBB not detected. Compiling without multithreading and without precise timing.]) ])], [test "x$with_tbb" == "xyes"], [PKG_CHECK_MODULES([TBB], [tbb])], [test "x$with_tbb" == "xno"], [], [AC_MSG_ERROR([invalid value $with_tbb for with_tbb.])] ) AS_IF([test "x$with_tbb" == "xno"], [TBB_CFLAGS="-DMATHICGB_NO_TBB"]) dnl ----- The librt dependency dnl On Linux TBB calls clock_gettime, which requires librt, but librt is not dnl linked in automatically. So we need to check for that. dnl the first AC_LINK_IFELSE causes tests for lots of C++ related things, dnl and these print out messages. So to avoid those messages appearing dnl after "if librt..." and before the result for that test, we do an dnl empty AC_LINK_IFELSE. Probably there is a better way. AC_LINK_IFELSE([AC_LANG_SOURCE([[]])], [], []) dnl We check if -lrt is necessary. We need librt if we are building with TBB, dnl if linking and compiling works when linking with librt but it doesn't dnl without linking with librt. AS_IF([test "x$with_tbb" == "xyes"], [AC_MSG_CHECKING([if librt is needed to support TBB on this platform]); oldLIBS=$LIBS; LIBS="$TBB_LIBS -lrt $LIBS"; oldCFLAGS=$CFLAGS; CFLAGS="$CFLAGS $TBB_CFLAGS"; AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#]include [<]tbb/tbb.h[>]], [[tbb::tick_count::now();]] )], [LIBS=$oldLibs; AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#]include [<]tbb/tbb.h[>]], [[tbb::tick_count::now();]] )], [AC_MSG_RESULT([no])], [AC_MSG_RESULT([yes]); RT_LIBS="-lrt"] )], [AC_MSG_RESULT([no])] )]; LIBS=$oldLIBS; CFLAGS=$oldCFLAGS; ) DEPS_CFLAGS="$MEMTAILOR_CFLAGS $MATHIC_CFLAGS $TBB_CFLAGS $GTEST_CFLAGS" DEPS_LIBS="$MEMTAILOR_LIBS $MATHIC_LIBS $TBB_LIBS $GTEST_LIBS $RT_LIBS" AC_SUBST(DEPS_CFLAGS) AC_SUBST(DEPS_LIBS) # Enable optional maintainer mode (off by default) dnl AM_MAINTAINER_MODE turns off automatic reconstruction of the build dnl files if the source build files have changed. A developer will want dnl those automatic reconstructions to happen so that changes to the dnl build system are actually carried out. However, a user might not dnl have the tools required to reconfigure and the need for dnl reconstruction might be spurious if the last-modified date is set dnl incorrectly on the build files. dnl dnl Passing the option [enable] to AM_MAINTAINER_MODE makes the dnl non-reconstruction feature available, but only when turned on by dnl passing the option –disable-maintainer-mode. This option is dnl apparently useful to some package distributors. AM_MAINTAINER_MODE([enable]) # Set up Automake dnl foreign: do not create the GNU-specific file COPYING and do not complain dnl that GNU-specific files like NEWS, README, AUTHORS and ChangeLog are dnl missing. dnl -Wall: set Automake to emit all warnings it can. Is NOT RELATED to setting dnl warnings for other tools. For example, it wil not make the compiler dnl get a -Wall option. dnl subdir-objects: Put object files in a directory structure based on dnl the directory structure of the source files. This way, two source dnl files with the same name in different directories do not conflict. AM_INIT_AUTOMAKE([foreign subdir-objects -Wall]) # if --enable-silent-rules is passed to ./configure or if V=0 is passed # to make, then the compilation output will be much less verbose making # it possible to spot warnings and errors as they go by. AM_SILENT_RULES() # Set up the $(LN_S) macro, which creates symbolic links AC_PROG_LN_S # set output variable INSTALL to the name of a BSD-compatible install program. # Requires install-sh to be present as a fallback, even on systems where # the fallback is not used. AC_PROG_INSTALL # Set up LibTool LT_INIT([disable-shared]) dnl Set the version for the library -- this concerns compatibility of the dnl source and binary interface of the library and is not the same as the dnl version of the project. AC_SUBST([MATHICGB_SO_VERSION], [0:0:0]) dnl Set up AC_OUTPUT to create each file by copying an input file dnl while substituting the output variable values. AC_CONFIG_FILES([Makefile build/autotools/mathicgb.pc:build/autotools/mathicgb.pc.in]) dnl Macro that is required to be at the end of any Autoconf script. dnl Creates config.status and launches it. AC_OUTPUT mathicgb-master/doc/000077500000000000000000000000001311555162500146765ustar00rootroot00000000000000mathicgb-master/doc/description.txt000077500000000000000000003251041311555162500177720ustar00rootroot00000000000000***** Contents - Introduction - High-level view of MathicGB - Installation for unix systems and Cygwin - Installation for Visual Studio - C++ concepts and miscellaneous MathicGB C++ stuff - Description of all files in MathicGB - Other projects ***** Introduction Since I'm going into industry I won't be able to continue to do much development on MathicGB. I have hope that the torch will be picked up and in this document I am writing about my thoughts and knowledge about MathicGB. I also make suggestions about projects that would improve MathicGB and I indicate for each how much effort I think it will be and how difficult I think it will be - some of these estimates may be way off. This is all current as of September 24, 2013. -- Bjarke Hammersholt Roune ***** High-level view of MathicGB The core engine of MathicGB is ClassicGBAlg, which implements the classic Buchberger algorithm with some improvements, and SignatureGB, which implements the Signature Basis Algorithm. These classes do not contain that much code, instead they use a lot of other classes to do their bidding. They have classes for keeping track of the basis, for keeping track of the S-pairs, for reducing polynomials and for representing the coefficients, monomials and polynomials. Some of the components used by the top-level algorithms are encapsulated behind virtual interfaces, so that different implementations can be chosen at run-time. This is notably the case for the reducers. For example, ClassicGBAlg implements F4, which is achived by having a reducer that does matrix-based reduction. Since the reducer is encapsulated behind a virtual interface, the top-level algorithm is unaware of whether it is currently doing F4 or the classic Buchberger algorithm. The low level components that take care of coefficients, exponents, monomials and terms are not encapsulated behind a virtual interface. Most of the inner loops in MathicGB contain an operation on one of these structures, so there would be too much overhead if each operation required a virtual function call. That is why MathicGB only supports a single kind of coefficient, exponent, monomial and term. Just like virtual functions, templates allow programming to an interchangeable interface, but the overhead of templates is in the time it takes to compile the program and in the size of the final executable. Templates do not impact the speed of the program, except through increasing the size of the final executable, which can lead to worse performance from the instruction cache on the CPU. My plan was for MathicGB to support many different kinds of coefficients, exponents, monomials and terms. I wanted to achieve this using templates to decouple these structures from the higher-level components that use them. I did not have time to complete this plan, yet my incomplete efforts in this direction has had a significant effect on all of the code and those changes might seem strange without knowledge of the end goal - that is why I mention this as part of the high-level overview. To complete the plan, all high-level components will need to be templates on the low-level structures that they use. For example, a structure to represent a polynomial will need to be a template on a polynomial ring and a structure for handling S-pairs will need to be a template on a monoid (the monoid is the part of a polynomial ring that has to do with monomials). None of these are currently templates in MathicGB, but they are written in a way that is intended to make it easy to turn them into templates. That way I could make many of the necessary changes one file at a time and thus test each little change one at a time. The more direct alternative would have been to do all the changes at the same time, which would have taken a month or two and MathicGB would not have been compilable during that time. The likely multi-week bug hunting party at the end of that would have been a wonderful time. Many classes in MathicGB have a typedef called Monoid and all monomial-related types are then referenced as sub-types of the Monoid. That could seem strange since there is only a single monoid that MathicGB can currently use, but the idea is that the Monoid type would turn into a template parameter and at that point the change for becoming a template should be much easier since the code is already written in terms of that template parameter/typedef. That is why the code is written like that. Note that there is no problem with using both virtual interfaces and templates. The virtual interfaces allows selection of a type at runtime, so the user does not have to recompile MathicGB just to choose a different reducer implementation. The templates allow a choice of types at compile time. These features combine beautifully. For example, the virtual Reducer interface could be a template on a polynomial ring. By putting the code that instantiates that interface into .cpp files, this allows the templated higher-level algorithms to use the Reducer interface without ever directly observing the code that implements the reducers, even though all the code consists of templates - including the high-level algorithm, the reducer interface and the reducer implementation. This way a change to the reducer implementation does not require recompilation of the high-level algorithm. There is an unfortunate pattern with highly templated programs where there ends up being a single file that instantiates most of the entire program. This single file can then take a long time to compile and it is not possible to compile in parallel since there is only a single translation unit that takes most of the time. Even if this pattern is avoided, it is often the case that all of the .cpp files include and instantiate the same temlates over and over again, leading to slow compilation. Hiding the templates behind templated virtual interfaces reduces this problem. For example, if the implementations of the templated virtual Reducer interface are hidden from the code that uses Reducers (that is, they only see the template Reducer interface), then that code never sees the Reducer implementations and therefore does not need to create its own instantiation of the Reducer implementations. So templates can step in when virtual interfaces are too expensive and then virtual interfaces at a higher level of the program can reduce the costs of using templates. That's the end goal I had for many of the changes in MathicGB. ***** Installation for unix systems and Cygwin gtest is downloaded automatically if it's not present (the download requires wget). It's used for the unit tests. tbb is necessary for parallel computation, but MathicGB will compile in a serial mode if tbb is not found by ./configure. pkg-config and autotools are required. mathic requires memtailor and mathicgb requires mathic and memtailor. If getting the source code from git, you need to do: ./autogen.sh ./configure make install Parallel builds with -jN are fully supported and safe. Setting memtailor, mathic and mathicgb up in multiple different configurations (release, debug, debug-without-asserts, release-with-asserts etc.) is a lot of effort. Instead, take this file: https://github.com/broune/mathicgb/blob/master/build/setup/make-Makefile.sh Then type ./make-Makefile.sh > Makefile then do "make". It'll download memtailor, mathic and mathicgb and link them up with each other in multiple configurations. The configure directories will be subdirectories of each project. The installed files will go in a common installed/ directory. Project(high-effort, medium-difficulty): Make nice packages for memtailor, mathic and mathicgb for the various distributions and Cygwin. Failing that, upload a source or perhaps even binary tarball somewhere. Project(medium-effort, medium-difficulty): Make a nice website for mathic. Project (medium-effort, low-difficulty): Set up a trac for MathicGB. ***** Installation for Visual Studio There are Visual Studio 2012 project files for each project in mathicgb/build/vs12. I have gotten these to work on both Visual Studio Pro 2012 Pro and Visual Studio Express 2012. Getting these files to work is more involved than just typing "make", though I found it to be worth it because Visual Studio is a first-rate development environment. You must download gtest (source release), tbb (binary release), memtailor (source), mathic (source) and mathicgb (source) and put them all in the same directory so that it has directories named: gtest\ tbb\ memtailor\ mathic\ mathicgb\ Now open mathicgb\build\vs12\mathicgb.sln. Select the configuration and platform that you want from the drop-down menues at the middle-top of the screen. You probably want the Release configuration and the x64 platform. Now compile everything by pressing F7. As of the time of this writing (October 3, 2013) the code compiles in MSVC and you should get an error and warning-free build. If other developers have picked up the project since then and they are not using MSVC, then likely you will need to make changes to the code to get it to compile on MSVC. Right click the mathicgb-test project in the Solution Explorer and left click "Set as StartUp Project". Now press F5 to run the unit tests. If you have installed tbb globally this might work (is that possible?), but otherwise you're going to get an error that the tbb dll could not be found. There should be a better solution to this, but what I found the easiest to do is to go into tbb\bin\intel64\cv11\ and copy all the files there into mathicgb\build\vs12\output\x64\Release\. That's for an x64 Release build. For a Win32 build, take the files from tbb\bin\ia32\cv11\ and copy them into mathicgb\build\vs12\output\Win32\Release\. For a different configuration than Release, replace Release with the name of the configuration. All these directories will already exist if you try building a file with that configuration and platform, which is what I'd recommend. After doing this, you should be able to press F5 in Visual Studio and get all the tests to run and pass. Project (Medium-effort, medium-difficulty): Find a better way of linking up with tbb that is easy to do and does not involve copying files around manually. Also make a .bat file that downloads all the necessary source and binary releases and links everything up - serving the same purpose as the Makefile written out by make-Makefile.sh. It is important that MathicGB isn't too hard to set up on MSVC because otherwise developers won't use it and then the code will stop working on MSVC. ***** C++ concepts and miscellaneous MathicGB C++ stuff These are things that will be helpful to know when developing for MathicGB. -- Papers To really get a good idea of the litterature you'll need to spend a lot of time reading papers (possibly years). To get started on what's relevant for MathicGB, here are a few suggestions: -the SB/ISSAC paper: http://arxiv.org/abs/1206.6940 This paper describes a lot of algorithms and data structures used in MathicGB. There is information here for both signature and classic Groebner basis computation. -mathicgb/doc/slides.pdf Slides from a talk I gave at Kaiserslautern University. It describes matrix-based polynomial reduction and goes into some detail about the implementation in MathicGB of that. -ABCD decomposition: http://www-polsys.lip6.fr/~jcf/Papers/PASCO2010.pdf A technique for reducing matrices used in MathicGB. -- Details on undefined behavior in C and C++ It is useful to know what things invoke undefined behavior and what the consequences are. Here's a good start on learning about that: http://dl.acm.org/citation.cfm?id=234990 http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html -- References are nicer than pointers First of all: pointers are perfectly fine when you need them! However, references are better when they can be used. If we ignore the syntactic difference, a reference is a pointer that must never be null or uninitialized and that will never change. Also, as a convention, a reference is never an owner of the object it refers to. If you have a pointer that satisfies those conditions, use a reference instead of a pointer. That way you are clearly unambiguously communicating these facts about the pointer/reference without having to write any comments. That's a Very Good Thing. It turns out that most pointers do satisfy these conditions, so most pointers should be references. The notation for accessing fields on a reference happen to be nicer than for pointers, too, though that's not really the main point. If you have a good reason to use a pointer instead of a reference in some specific case, then by all means go ahead. -- RAII and why owning pointers are evil A resource is something that needs to be released when you are done with it. The most common kind of resource is a piece of memory, but there are many others: files, internet connections, database connections, threads and so on. When you are holding a resource, you will, at the very least, get a resource leak if you forget to release the resource. You might also release the resource twice by mistake or keep using the resource after releasing it. Those things are likely to crash your program. Manually freeing every resource exactly one time at the right time and then never using it again is error prone. That's why memory leaks are a common problem and it is why garbage collection is so popular, even though garbage collection only takes care of the memory resources and it introduces its own issues. std::unique_ptr is the premier example of RAII. http://en.cppreference.com/w/cpp/memory/unique_ptr https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization RAII stands for Resource Acquisition Is Initialization. RAII solves most of the resource management problem and it's a stand-out great feature of C++. The idea is that every resource is owned by a dead-simple handle object. The destructor of the handle object frees the resource. Every resource is given over to a handle object immediately. This way it is impossible to forget to release the resource, because you do not need to do anything to make it happen - it happens automatically when the handle goes out of scope (if on the stack) or if the owner of the handle is destructed. The presence of a handle then also makes it immediately clear what object owns the resource - it is whatever object holds the handle. You will know what owns what just by looking at the types involved. Using std::unique_ptr has two phases: first allocate an object on the heap, then construct a unique_ptr handle to own/manage the object. The problem here is that something bad, like an exception, might happen between these two steps, or you might forget the second step. Here's a subtle example where this happens: void foo(std::unique_ptr, std::unique_ptr); void bar() { foo(std::unique_ptr(new int(1)), std::unique_ptr(new int2)); } This is a memory leak. The order of evaluation of parameters to functions is unspecified in C and C++, and it's even valid to interleave the execution of parameter expressions, so this is a valid order of execution: 1. new int(1) 2. new int(2) 3. constructor of the first std::unique_ptr 4. constructor of the second std::unique_ptr If the allocation in step 2 causes an exception (std::bad_alloc, or maybe something more excotic if it were a more complicated class than int), then the int allocated in step 1 will be leaked. The solution to all of these problems is to avoid writing new whenever you can (which is almost always). Instead call a function that both allocates the resource and also initializes and returns the handle. In C++14 there is supposed to be a std::make_unique that will do that. C++14 isn't here yet, so instead there is a make_unique defined in stdinc.h - use that one.. This is how to fix bar(): void bar() { foo(make_unique(1), make_unique(2)); } The execution of function calls cannot be interleaved in the that dangerous way, so there is no problem when doing it this way. Not only is this now safe from memory leaks, it is simpler, requires less typing and looks nicer too. :) Here is another example: http://tipsandtricks.runicsoft.com/Cpp/SmartPointerMemLeak.html In the absence of RAII, what you are left with is owning pointers and other owning handles that do not know how to free their resource. In a program full of such things, it is generally difficult to figure out what object owns what resource. It can be cumbersome and error prone to do the right thing even when ownership is clear. Here is a reasonable way of implementing foo() and bar() in a world without RAII, complete with the necessary comment to communicate the pass of ownership: // Hey everyone, remember that foo takes over ownership of both pointers! void foo(int*, int*); void bar() { int* a = new int(1); int* b; try { b = new int(2); } catch (...) { delete a; throw; } foo(a, b); } Not so nice. Also, what if bar ended like this: foo(a, b); delete a; delete b; } That would be a bug, but not a very obvious one - you need to go read the comment from foo() about ownership being passed on to know what's wrong - that comment might be in a different file. It could be worse: ownership could be passed for the first parameter, but not the second. Then you'd really need to make sure you got things just right. RAII saves us from worrying about most of this kind of stuff. RAII is good. Learn to love RAII. Sometimes RAII is not a good option, for example when the amount of context required to free a resource makes the handle object too large which then becomes a memory consumption or cache size issue. In those cases you might need to not use RAII, but then at least try to encapsulate this ugliness behind a nice interface that completely hides the ugly truth from the rest of the program. Here's an anti-pattern for RAII, which cannot always be avoided, but usually it can: void foo(const unique_ptr& ptr); why does foo() care about the int being handled from a unique_ptr? It cannot change the unique_ptr, so all it can do with it is the same thing you can do with a pointer. Furthermore, this can be a performance issue, because you get a double indirection. The reference is an indirection and the unique_ptr is an indirection, so in performance terms this is like passing an int**. If ptr cannot be null, this is much better: void foo(const int&); Since copying an int is no big deal, this is even better: void foo(int); If ptr can be null, then you do need a pointer, but there's no reason to specify that it must be a unique_ptr: void foo(int* ptr); This is fine and not a contradiction to the idea of using RAII. The reason for that is that ptr does not own what it points to and no ownership is being passed. The evil pointers are the pointers that own what they point to. -- r-value references and move semantics Another write-up of these topics: http://thbecker.net/articles/rvalue_references/rvalue_references.pdf Among many other things, move semantics solves the inefficiency in this example: std::string foo(const std::string& str) {return str + '!';} void bar() { auto str = foo("hello world"); } This is what happens here: 1. A temporary std::string is constructed in bar to hold "hello world" 2. foo gets a reference to that string object. 3. foo constructs a new string object that holds "hello world!" 4. bar receives that new string object. 5. bar deconstructs the old string object holding "hello world" Now you might say that it looks like there would be a copy, because we need to copy the object returned from foo into str in bar(). In fact the compiler is free to elide this copy: http://en.wikipedia.org/wiki/Return_value_optimization Still, this is not efficient. We are allocating memory to hold "hello world". Like std::vector, std::string is free to over-allocate memory, so that original std::string might well have enough capacity to hold the final string "hello world!". We should reuse the memory from the first object to hold the final string. Then there might be only the single allocation instead of two. We declared the reference to be const, so we should not alter the passed in std::string. We could proceed with overloading like this: std::string& foo(std::string& str) {return str += '!';} std::string foo(const std::string& str) {return str + '!';} It's true that we now re-use the passed-in string, but this is an abomination! The caller might be holding a non-const std::string but still not want it to change. In some other part of the program, it might be very important that that std::string does not change. Besides, this code: auto str = foo("hello world"); will actually call foo(const std::string&). That's a very good thing, too. The reason for that is that you should not being doing things like this: std::string& str = std::string("hello world!"); The right hand side here constructs a temporary std::string object which str then refers to. That temporary object goes away (is destructed) as soon as that line is done executing. If the next line is std::cout << str; then str is now referring to an invalid object and this might well crash the program. To save us from this fate, C++ will flag an error on the code above. The compiler will say something like this: cannot bind an r-value reference to an l-value reference All the references that we know and love and that are spelled with a & (like int&) are l-value references. An r-value reference is something like the above example: it is a reference to something unnamed. In classic C++, the main (only?) way to get an r-value reference is to construct a temporary object. Temporary objects are going to die very soon. So it's always a bad idea to have an l-value reference (that is, a usual reference) bind to an r-value, because that's going to be an imminent disaster like in this example. So C++ flags that kind of thing as an error. That's why this code: auto str = foo("hello world"); does not select the foo(std::string&) overload - the temporary std::string object that gets constructed is an r-value, so we cannot bind it to an l-value reference and std::string& is an l-value reference. The overload that does get selected is foo(const std::string&), which shows that we CAN bind r-values to CONST l-value references. I am guessing that the idea here is that changing temporary objects does not make much sense, since they are going to away very soon anyway. Aha, you might object, does that not make this code an imminent disaster, just like before? const std::string& str = std::string("hello world!"); std::cout << str; Nope. There is no error here. Not a compile-time error and not a run-time error. This will work. The reason for that is that if you bind a temporary object to a CONST l-value reference, then the lifetime of the temporary object is extended to the life-time of the reference. So by binding to a const l-value reference, we are preventing the temporary std::string from being destructed at the end of the line. What's the point of a special rule for const l-value references? By treating const l-values specially, we are allowing code like this to work: std::string foo(const std::string& str) {return str + '!';} void bar() { auto str = foo("hello world"); } If we could not bind the temporary std::string from the caller (an r-value) to the const std::string& (an l-value reference) that foo accepts, then this sort of thing would be a compile-time error. You'd be forced to do this: void bar() { const std::string bah("hello world"); auto str = foo(bah); } Wouldn't that just be sad? So const l-value references are special. (You might ask: why not have non-const l-value references also work in this special way? I don't know a good reason, but the fact is that they do not.) So what can we do? C++11 to the rescue. In C++11 we have a way to spell r-value reference. An int r-value reference type is spelled int&&. So we can do this: std::string&& foo(std::string&& str) {return str += '!';} std::string foo(const std::string& str) {return str + '!';} This is a bit better than before. The first overload will only be used when the parameter is a non-const r-value std::string, like in this case: auto str = foo("hello world"); However, the r-value overload will not be used here: std::string importantStringThatShouldNotBeChanged = "don't change me"; auto str = foo(importantStringThatShouldNotBeChanged); Here the important string object is not a temporary object, so it's not an r-value (more precisely, it has a name, so it's not an r-value). There we cannot bind the important string object to an r-value. So we only use the r-value overload when the object being passed in is a temporary object. That means that no one else in the program can reasonably have a reference to it (how would they?). So it's always going to be OK to steal that object and use it for our own purposes. So this is a lot better. It's still not good, though. Consider this example: const std::string& str = foo("hello world"); std::cout << str; We are expecting foo() to return a temporary object and to be safe we are using a const l-value reference to capture the temporary object. That way we know that the life-time of the temporary will be extended so that str will still refer to a valid object on the next line when we print it out. Except it doesn't work like that. The problem here is that foo doesn't return a temporary object, not from the compiler's perspective. It returns a reference. Extending the life-time of that reference does nothing. What we need is to extend the life-time of the temporary object that was passed to foo. Yet the compiler does not see that temporary object being directly bound to a const l-value reference. It just sees that object being passed to foo(). So the life-time does not get extended. It does not matter that foo() happens to return a reference to the same object. What can we do? We can fix it by returning a std::string object instead of returning a referenceL std::string foo(std::string&& str) {return str += '!';} Of course now there will be a copy, so we are back to square one - almost. We still know that no other part of the program is supposed to have a reference to str. We are the only ones holding str, so we are also the only ones holding the memory used by str. If we could somehow break the encapsulation of std::string and take the pointer to that memory from inside str and directly get the returned object to just use that pointer, then there would not need to be a copy. We cannot break the encapsulation of std::string (or at least shouldn't), but it happens to be that C++11 has a way of achieving exactly this goal. It's called std::move. We can use it like this: std::string foo(std::string&& str) { str += '!'; return std::move(str); } std::move is a template. What it does is to take an l-value reference T& and return an r-value reference T&& to the same object. Think of it as a cast - it changes the type of something, but it doesn't do anything other than that. So by using std::move, we can force the compiler to think that something is an r-value, even when it isn't (and str isn't, see below). The magic ingredient here is that std::string has a constructor that accepts a std::string&&. That constructor steals the memory from the passed-in std::string (and removes it from that std::string). So the memory is transferred with no copying and no allocation. That is safe because that r-value reference is supposed to refer to a temporary object that is about to die, so no one else has a reference to it - so no one should ever know that its memory has been stolen. It's like stealing a painting out of a burning building - no one is going to know the difference. We used std::move to trick the compiler into thinking that our str was an r-value reference, but we only did that in a situation where we knew that no one else would use that std::string anymore - because we also accepted that std::string as an r-value reference outselves. So as long as we only use std::move at the right places, all is well. You might be saying: wait a moment, isn't str ALREADY an r-value reference? It's type is std::string&& and you said that && means r-value reference. The type of str is indeed std::string&&. However, consider this: std::string q; foo(q); Here foo(const std::string&) gets called, but the type of q is NOT const std::string&. It is std::string. The point here is that when you want to figure out what kind of reference you get, do not look at the type of the thing, look at the context. If something doesn't have a name, then it's an r-value reference in that context. If it has a name, then it's an l-value reference in that context. Both q and str have names, so when we use the names q and str in the program, we get l-value references, not r-value references. It doesn't matter that q's type is not an l-value reference and it does not matter that str's type is not an l-value reference. It's not about the type. It's about having a name or not having a name in a specific context. This is where we got to: std::string foo(std::string&& str) { str += '!'; return std::move(str); } std::string foo(const std::string& str) {return str + '!';} The first overload will reuse memory that isn't beeing used anywhere else anyway and the second overload will allocate new memory because we might need to preserve the original passed-in std::string. So far so good. We can actually simplify this a bit: std::string foo(std::string str) { str += '!'; return std::move(str); } Here we always construct an object from the parameter, but we use std::move to return it, so there is no copy there (there is something called the return value optimization that is relevant here, but let's save that for later). Let's consider four ways of calling foo: 1. std::string a("don't change me"); foo(a); 2. foo(std::string("change me if you want")); 3. foo("I'm a string"); 4. std::string b("you can change me too"); foo(std::move(b)); For 1, a has a name, so it's an l-value reference. std::string has a constructor that takes an l-value reference std::string&, and that constructor copies. So there is a copy, but only the one, just as before. For 2, we construct a temporary unnamed object, which is then an r-value reference, and std::string has a constructor that accepts a std::string&& parameter. That contructor steals the memory without copying, so there is no copy at all, just like before. For 3, that's the same as 2, except the temporary std::string is implicit. For 4, the b in std::move(b) is an l-value reference just as for 1, but we use std::move to cast it to an r-value reference, so what happens is the same as for 2 and 3: the memory gets stolen out of b. As long as we remember never to use b again, that's fine. Consider this example: std::string a("I'm a string"); std::string b("You're a string"); b = std::move(a); std::string also has an operator=(std::string&&) which steals the memory out of the parameter. So what happens in the third line here is that b frees its own memory and steals the memory out of a - which is fine as long as we remember never to use a again. The precise contract is if that a standard library object is moved out of, then that object is placed in a valid but unspecified state. It is guaranteed that it is OK to destruct an object that has been moved from, but otherwise there is no general guarantee, though some classes might give stronger guarantees. std::vector has move (r-value) a constructor and a move operator= just like std::string does. So does lots of classes in the standard library in C++11. Consider this: std::vector v; v.push_back("1"); v.push_back("2"); v.push_back("3"); // ... v might incur several reallocations during all these push_backs. Inside the reallocation, std::vector knows that all the old objects that it has been storing are going to disappear in a moment (modulo a caveat about a different feature called noexcept that I don't want to get into here). So no other part of the program ought to be looking at those objects at any time in the future. So it's safe to move the strings using std::move and that way the new strings just steal the memory from the old strings instead of allocating new memory and copying. Objects that can be moved are said to have move semantics. std::unique_ptr has move semantics, though it uses them for a different purpose than std::string and std::vector. std::unique_ptr never copies anything, so the point is not to avoid copies. The point is that only a single unique_ptr should ever own the memory being pointed to. So we want this to be a compile-time error: std::unique_ptr a = make_unique(1); std::unique_ptr b; b = a; If we allowed the third line, then both a and b would now own the memory, leading to a double free. We could set a's pointer to null in preserve the invariant, but then it becomes very easy to null out your std::unique_ptr by accident. It's quite confusing for "b = a" to change a. We only expect it to change b. If you try the code above, you will get an error on the third line. The reason for that is that std::unique_ptr has an operator=(std:unique_ptr&&) but not an operator=(std::unique_ptr&) a is an l-value reference, and we already know that we cannot bind l-value reference to the r-value reference type std::unique_ptr&&. So this is a compile error. To fix it, we can do this: b = std::move(a); Now we have cast a to an r-value reference. What happens here is that b gets a's memory and a is set to null. This is no longer confusing. There is no mystery that a got changed since we explicitly did std::move(a). Did you spot this line? std::unique_ptr a = make_unique(1); Here we are initializing a from a std::unique_ptr, and we did not use std::move to cast the other std::unique_ptr to an r-value. Why is that OK? Because it's already an r-value - it doesn't have a name. So no other part of the program should have a reference to that object and therefore moving out of it is safe. -- implicit moves Consider this code: std::unique_ptr& baz() { auto ptr = make_unique(1); *ptr = 2; return ptr; } This will compile but it's very bad - we are returning a reference to an object that lives on the stack inside the function. That object will no longer be valid when the function returns. So how about this: std::unique_ptr&& baz() { auto ptr = make_unique(1); *ptr = 2; return std::move(ptr); } Is that OK? No it's not and for exactly the same reason - l-value references that refer to invalid objects are bad and it's just the same thing for r-value references that refer to invalid objects. You need to do it like this: std::unique_ptr baz() { auto ptr = make_unique(1); *ptr = 2; return std::move(ptr); } Here we move the memory of ptr into the returned object using std::unique_ptr's move constructor (that is, the one accepting an r-value reference), but we do not return the ptr object itself - that object is left to die when the function returns (it's a harsh world for a stack-allocated variable). In fact, we can rewrite baz like this: std::unique_ptr baz() { auto ptr = make_unique(1); *ptr = 2; return ptr; } This looks wrong at first sight because std::unique_ptr's constructor requires an r-value reference. Clearly, ptr has a name, so it's an l-value. What gives? The point is that we are returning a local object - one allocated on the stack. When we get to the return statement, the compiler knows that this object is just about to go out of scope and be destructed. This is exactly the same situation as for a temporary object - it is just about to be destructed. So in this very specific circumstance, it is OK to let ptr be an r-value (just as if it had been an unnamed temporary), and that's how it is in C++11. So the std::move is superfluous in this case. -- universal references and perfect forwarding So far there has been a simple rule: & means l-value reference and && means r-value reference. It's not that simple, unfortunately. Suppose we want to make out own 2-parameter make_unique function. Let's try that: template std::unique_ptr make_unique(const Arg1& arg1, const Arg2& arg2) { return std::unique_ptr(new T(arg1, arg2)); } This isn't so good, though. What if T's constructor requires a non-const l-value reference? What if T's constructor requires an R-value reference? References can also be volatile. So we need overloads for Arg1& const Arg1& volatile Arg1& volatile const Arg1& Arg1&& const Arg1&& volatile Arg1&& volatile const Arg1&& That's 8 overloads. We need the same thing for the second argument, leading to 8*8=64 overloads. If we want to offer a 10 parameter make_unique, then that would require 8 raised to the power of 10 overloads. Not good. In fact we only need a single overload, namely this one: template std::unique_ptr make_unique(Arg1&& arg1, Arg2&& arg2) { return std::unique_ptr(new T(arg1, arg2)); } So how does this work? Suppose the arguments are const int&, like here: const int i = 1; make_unique(i, i); Then Arg1 and Arg2 gets resolved to const int&. So it becomes like this: template std::unique_ptr make_unique(const int& && arg1, const int& && arg2) { return std::unique_ptr(new T(arg1, arg2)); } You can't directly write & && without an error, but if that appears in a case like this, then there are rules for how to resolve it. The rules are: & & becomes & & && becomes & && & becomes & && && becomes && This is called reference collapsing. So it becomes: std::unique_ptr make_unique(const int& arg1, const int& arg2) { return std::unique_ptr(new T(arg1, arg2)); } That's exactly what we wanted! Let's try that again for a r-value reference parameter: volatile int i; make_unique(std::string("hi"), i) Here we get Arg1 to be std::string&& and since && && becomes &&, we get std::unique_ptr make_unique(std::string&& arg1, volatile int& arg2) { return std::unique_ptr(new T(arg1, arg2)); } That's the right overload that we want, but the implementation of the function isn't what we want. arg1 was passed to us as an r-value, so we want to pass it to the constructor of T also as an r-value. However, since we gave arg1 a name, it counts as an l-value. What we want is this: std::unique_ptr make_unique(std::string&& arg1, volatile int& arg2) { return std::unique_ptr(new T(std::move(arg1), arg2)); } However, we can't just put a move in there, because then we'd also be casting other parameters to r-values, even those that were not passed to us as r-values. What we need is to do a conditional cast, a cast that says: "cast this to an r-value, but only if Arg1 is an r-value reference". That's exactly what std::forward() does, so this is the final and correct implementation: template std::unique_ptr make_unique(Arg1&& arg1, Arg2&& arg2) { return std::unique_ptr (new T(std::forward(arg1), std::forward(arg2))); } This is called perfect forwarding, because we managed to pass the exact type of the parameters on to the constructor of T, no matter what kind of type it is - and we didn't need 64 overloads to do it. The main consequence of this is that && doesn't necessarily mean r-value when used with a template parameter. There's even a further quirk on this: this process I just described ONLY works when the parameter is "T&&" where T is a template parameter. If you do for example "const T&&" and try to pass in an l-value, then you'll get an error - reference collapsing will not occur. Or if you do "volatile T&" and then try to pass in a const volatile int, then you'll still get an error because the template will only accept non-const volatile T's. So template parameters of the form "T&&" are very special and it is only in this context that && doesn't necessarily mean r-value. Well, almost (I'm sensing a theme here). auto is kind of like a template parameter and it has the same special case. If you do: auto&& x = ... Then now x will be of whatever kind the right hand side is following the same reference-collapsing process as I just described: const std::string a; auto&& aa = a; // aa is a const std::string& auto&& bb = std::string(); // bb is a std::string&& Here aa has the type of an l-value reference even though it is declared with &&. Again, this only works for the special case of "auto&&". It does not work for "const auto&&", for example, so this is an error: const std::string c; const auto&& cc = c; The problem is that cc is now hard-coded to be actually an r-value reference and c is an l-value. Because the cases for "T&&" and "auto&&" are so special, they've been given a special name: universal reference. They are called that because they can refer to any type you want. A final point about r-value references: an r-value reference (of whatever kind) extend the life of a temporary, just like a const l-value does. So this is OK: std::string&& str = std::string("hello world!"); std::cout << str; http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11 -- Range-based for loops They look like this: std::vector v; for (int x : v) { // ... } x will go through each element in v in turn using a hidden iterator. This works for any container v where std::begin(v) and std::end(v) returns iterators. The default implementation of these just call v.begin() and v.end() (they are templates that you can partially specialize to do something else if you want), so it'll also work with any class that has .begin() and .end(). range-based for loops are awesome. This is the same thing as above in C++03: std::vector v; std::vector::const_iterator end = v.end(); for (std::vector::const_iterator it = v.begin(); it != end; ++it) { int x = *it; } Using auto, this could be improved to auto end = v.end(); for (auto it = v.begin(); it != end; ++it) { int x = *it; // ... } and if we do not care about the possible inefficiency of not caching v.end(), we can further simplify to: for (auto it = v.begin(); it != v.end(); ++it) { int x = *it; // ... } This is a much noisier syntax than the much simpler range-based for. There are two main idioms for using range-based for. If you want to do a scan through a range where you modify the contents of the range, do: for (auto& x : v) if you only want to observe the elements of the range, do for (const auto& x : v) This way, it's always immediately clear what's going on. The alternatives that I would advise to avoid (unless there's some good reason) are: for (auto x : v) // could be inefficient, doesn't spell out "const" and for (auto&& x : v) // universal reference makes intended constness unclear -- don't call a method getFoo(), findFoo(), calculateFoo(), pleaseComeBackToMeFoo() or anything like that, just call it foo() It's more succint, reads better and is just as clear. Do use setFoo or similar if you want to set a field. -- pointerness and reference-ness is a part of a variable's type The format for a variable declaration is "type variableName". Pointerness and variableness is part of the type, so it's int* a; int& a; and not int *a; int &a; and also not int * a; int & a; This notation has the drawback for this case, which becomes confusing: int* a, b; this is equivalent to int* a; int b; which is absolutely horrible, of course. The answer is simple: never declare two variables in one statement using a comma. -- don't use using You've likely noticed all the std:: prefixes by now. MathicGB does not have "using namespace std;" anywhere. There's not even "using std::vector;" or anything like that. using should not be used in headers because code that includes that header will be forced to use the using which might cause name clashes. using should therefore also not be used in implementation files because then moving code between headers and implementation files becomes annoying. I didn't like the std:: prefixes initially, but you get used to it. Now it doesn't bother me at all. -- if it can be const, make it const Bugs generally happen when something changes. const things don't change. So there will be fewer bugs! It can also aid optimization in a special case. The const in const int& doesn't help the optimizer at all, since it would be possible to cast away the constness or change the value using a non-const reference. However const int does help the compiler (not a reference), because objects originally declared const are not allowed to change, not even using const_cast. Example: int a = 1; // can change const int& aa = a; const_cast(aa) = 2; // OK (well, at least according to the standard) const int b = 1; // must not change const int& bb = b; const_cast(bb) = 2; // undefined behavior! -- Do #includes from least general to most general This way you are more likely to spot missing include files in headers. -- use auto whenever you can unless you've got a special reason not to Bad: std::vector> pairs(std::begin(r), std::end(r)) Good: auto pairs = rangeToVector(r) Get an editor that will show you the types of variables as a tooltip on mouse-over if you want to know the types. http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/ -- Learn to love the assert MathicGB has MATHICGB_ASSERT. You'll see it sprinkled liberally all over the code. If you can assert on it, then do assert on it. If the debug build gets to slow from a particularly slow assert, then profile the debug build (yes, that makes sense! :) and disable just the few asserts that were the problem. Assert is your best friend in this world when programming. -- The format of an X.cpp file Note that no file contains anyone's name in the copyright header. We don't want to get into discussions about how much or little someone needs to do to put their name there. It gets hairy when parts of a file are moved elsewhere. Long lists of names in files also isn't useful to the purpose of the project. // MathicGB copyright 2013 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "X.hpp" // other includes MATHICGB_NAMESPACE_BEGIN // code MATHICGB_NAMESPACE_END The purpose of the namespace macroes is to avoid having to indent everything by a level, which editors will otherwise want to do. --The format of a X.hpp file // MathicGB copyright 2013 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_X_GUARD #define MATHICGB_X_GUARD // includes MATHICGB_NAMESPACE_BEGIN class X { // ... }; MATHICGB_NAMESPACE_END #endif -- whitespace No tabs. Indentation is 2 spaces per level. If you are used to 8 space indent, you may think that 2 space indent makes code unreadable. It doesn't. It's just hard for you to read because you've trained your eyes to focus on the spot 8 spaces ahead and now you have to correct the position of your eyes constantly until your habit adjusts. I find 8 space indent unreadable for the same reason - I'm used to 2 space indent now, so I have to adjust my eyes too all the time when I read 8 space indented code. It's got nothing to do with the inherent readability of 2 versus 8 spaces, it's got to do with a habit of where to focus one's eyes. 2 space indent preserves horizontal space and is no less readable than 8 or 4 space indent, so that's why I'm using it. An opening { goes on the same line, unless the current line is indented and the next line is indented to the same level. In a parenthesized expression that does not fit on a line, the outer () is indented in the same way as {}. For example (imagine that these examples don't fit on a line): int Foo::bar( int x, int y ) const { // ... } int Foo::Foo( int x, int y, ): mX(x), mY(y) { // on own line since previous line is indented to same level // foo } -- names Macroes are ALL_UPPER_CASE and prefixed with MATHICGB_. CamelCaseIsTheThing otherwise. First letter of TypeNames is capitalized. First letter of functions and variables is lowerCase. Member variables are prefixed with an m, so mMyMemberVariable. Project(low-effort, low-difficulty): Describe the coding style more clearly and in more detail. Project(medium-effort, low-difficulty): Not all of MathicGB code entirely follows this coding style. Reformat that code. Project(medium-effort, medium-difficulty): Set up an automatic coding style checker to check the coding style. -- exceptions Exceptions are used to signal errors. Code should be exception safe at least to the extent of not crashing or leaking memory in the face of exceptions. ***** Description of all files in MathicGB *** mathicgb/Atomic.hpp Offers a MathicGB alternative to std::atomic with some of the same interface. Use this class instead of std::atomic. It was necessary to use this class because the std::atomic implementations that shipped with GCC and MSVC were so slow that they were just completely unusable. This is supposed to be better in newer versions. When not on MSVC or GCC, Atomic is simply a thin wrapper on top of std::atomic. Atomic also has another use in that you can define MATHICGB_USE_FAKE_ATOMIC. Then Atomic does not actually implement atomic operations. This way, we can measure the overhead for atomicity and memory ordering by running on one thread, since the atomicity and memory ordering is not necessary for one thread. Project (medium-effort, easy-difficulty): Figure out if GCC and MSVC really do ship a usable-speed std::atomic now and, if so, which versions are good and which are bad. Then let Atomic be implemented in terms of std::atomic on those good versions while retaining the fast custom implementation for the bad versions. The main effort involved here is in getting access to all the different versions of GCC and MSVC. This project could also be done for Clang. *** mathicgb/Basis.hpp A container of Polynomials that does nothing fancy. There is really no reason for this class to exist - it should be replaced by std::vector. The class uses std::unique_ptr, but since Poly now has move semantics there is no reason for using unique_ptr here. Project: Remove class Basis and replace it with std::vector. *** mathicgb/CFile.hpp .cpp A RAII handle for a C FILE*. The purpose of using the C IO interface instead of iostreams is that the former is faster to a ridiculous degree. This class wraps the C IO interface to be more useful in a C++ context. For example the file is automatically closed in the destructor and if the file cannot be opened then an exception is thrown instead of returning a null pointer. Project (small-effort, easy-difficulty): Grep for FILE* and see if there's any place where an owning FILE* can be replaced by a CFile. *** mathicgb/ClassicGBAlg.hpp .cpp Calculates a classic Groebner basis using Buchberger's algorithm. MathicGB implements the classic Groebner basis algorithm for comparison and because sometimes that is the better algorithm. MathicGB's classic implementation is not as mature as the ones in Singular or Macaulay 2, but it can still be faster than those implementations in some cases because of the use of fast data structures from Mathic. The matrix-based reducer implementation (F4) also IS the classic Buchberger implementation, since the skeleton of those two algorithms is the same. The only difference is how many S-pairs are reudced at a time. ClassicGBAlg has a parameter that tells it at most how many S-pairs to reduce at a time. Choose 1 for classic computation and more than 1 for matrix-based reduction. Project (high-effort, high-difficulty): The heuristic used for the preferable way to bunch S-pairs together for the matrix-based reduction is to select all of the S-pairs in a given degree, up to the maximum number of S-pairs allowed by the parameter. This is exactly the right thing to do for homogeneous inputs. It it not at all a good idea for non-homogeneous inputs. The grading used is just the first grading/row in the monomial order, so even for homogeneous inputs this can be bad if the ordering used does not consider the true homogeneous degree before anything else (for example it might consider the component first). Make up a better way to bunch S-pairs together. For example sugar degree. There will need to be lots of experiments here. This class prints a lot of nice statistics about the computation process. This code is a good example of how to use mathic::ColumnPrinter for easy formatting. The statistics are collected individually from different classes instead of using the MathicGB logging system. For example a manual timer is used instead of a logging timer. Project (medium-effort, medium-difficulty): Change the statistics being reported to be collected via the MathicGB logging system. This may require expanding the capabilities of the logging system. You may also want to add additional interesting statistics gathering. You'll need to measure the difference between compile-time disabling all logs and then enabling them all at run-time (but not enabled for streaming output, because that will always be slow). The difference in time should preferably be < 2%. If that's not the case, then you'll need to disable some of the logs by default at compile-time until it is the case. The Buchberger implementation always auto top reduces the basis. There is an option for whether or not to do auto tail reduction. This option is off by default because it is too slow. There are two reasons for that. First, the auto tail reduction is done one polynomial at a time, so it is not a good fit for the matrix-based reducers. Second, we need a better heuristic to select which polynomials are auto tail reduced when. Project (medium-effort, easy-difficulty): When using a matrix-based reducer (as indicated by a large requested S-pair group size), tail reduce many basis elements at the same time instead of one at a time. Project (medium-to-large-effort, medium-to-hard-difficulty): Figure out and implement a good heuristic that makes auto tail reduction a win. For example, it probably makes sense to auto tail reduce basis elements that are frequently used as reducers more often than basis elements that are almost never used as reducers. Project (medium-effort, medium-difficulty): Currently all the basis elements are inserted into the intermediate basis right away. We might as well wait with inserting a polynomial if it will not participate in any reduction or S-pair for a long time yet. This is especially so for homogeneous inputs, where there is no reason to insert a basis element in degree d until the computation gets to degree d. If we also wait with reducing these input basis elements until they finally get inserted, then that would, for homogeneous computations, furthermore ensure that all polynomials are both top and tail reduced all the time without re-reductions. *** mathicgb/F4MatrixBuilder.hpp .cpp *** mathicgb/F4MatrixBuilder2.hpp .cpp These classes are used by F4Reducer to construct the matrix used in F4. The code is parallel. This is an important piece of code because matrix construction can be a large part of the running time of matrix-based reduction (see slides). There are lots of ways of improving the reduction code and if all of those ideas are realized, then it might turn out that matrix construction will end up being the dominant use of time for F4! F4MatrixBuilder is the first version that does left/right and top/bottom splitting right away as the matrix is constructed (see slides and ABCD paper). F4MatrixBuilder2 postpones that split until after the matrix has been constructed. The advantage of F4MatrixBuilder is that it does not require a second splitting step, which enables it to run faster. However, without a second step there is then no way to sort the rows of the matrix within the top and bottom parts, so they appear in some arbitrary permutation. This makes the cache performance of the subsequent reduction worse, so that actually F4MatrixBuilder causes a slower total computation time than F4MatrixBuilder2 even though F4MatrixBuilder2 takes more time to construct the matrix. The interface for the two classes is the same. First the user describes the required matrix and then that matrix is constructed. Parallelism is achieved here by having each core work on separate rows of the matrix. The main point of synchronization between the cores is that they need to agree on which monomial has which column index. This is achieved via a lockless-for-readers hash table, implemented using std::atomic (well, actually mgb::Atomic, but it's the same thing). To understand the parallelism here you will need to understand how lockless algorithms work and the interface of std::atomic, which is going to be a significant effort to learn. The outcome of this way of doing it is that look-ups in the hash table are no slower on x86 than they would be in a serial program - it's the same CPU instructions being run (there might be a slight slowdown if contending for a cache line with a writer, but that's very rare). Writers do need to hold a lock for insertion, but since look-ups are much more frequent than column insertions, this is not so bad. TBB (Intel Thread Building blocks) is used to keep track of the work items to do so that cores can do work-stealing without much overhead. Project (medium-difficulty, medium-effort): An advantage of F4MatrixBuilder2's approach is that we can output the matrix and get a raw matrix that is not processed in any way. This matrix can then be used as input to other F4 projects to compare the speed of implementations. The project is to make this happen - write the output code and benchmark other projects on those matrices. This is already somewhat done, in that MathicGB can input and output matrices, but this is only done for the F4MatrixBuilder where the matrix is already split into ABCD parts. Other projects won't know what to do with a matrix in that format. Project (medium-difficulty, high-effort): Determine if any other project's matrix construction code is competitive with MathicGB. I do not think that this is the case, but it could be - I haven't measured. Quantify how much better/worse MathicGB is for matrix construction and determine the reasons for the difference. If there is something else competitive, either improve MathicGB using those ideas or build that other project as a library and make MathicGB able to use that other project's code for matrix construction. Project (possibly-impossible, unknown-effort): Significantly simplify the matrix construction code without making it slower (measure measure measure) or reducing its capabilities. Project (low-difficulty, low-effort): Count the number of lookups versus the number of insertions in the hash table to verify and quantify the claim made above that lookups are much more frequent than insertions. The purpose of this is to find out the number of cores where contention for the insertion lock becomes significant. This can be done just by looking at the matrix - each non-zero entry was a lookup, each column was an insertion. Get numbers for a wide variety of matrices. Project (medium-difficulty, medium-effort): Optimize the insertion code. See if you can reduce the amount of time where the insertion lock is held. If you determine that there is contention for the insertion lock and this really is a problem, consider using several insertion locks, for example 10 locks, one for each hash-value/bucket-index modulo 10. Project (medium-difficulty, low-effort): Make F4MatrixBuilder offer exception guarantees. At least it should not leak memory on exceptions. I think F4MatrixBuilder2 might need this too. Project (low-effort, low-difficulty): Rename F4MatrixBuilder and F4MatrilxBuilder2 to something more descriptive. Project (possibly-impossible, high-effort): Make F4MatrixBuilder2 construct its matrix faster than F4MatrixBuilder does. Then remove F4MatrixBuilder. Project (possibly-impossible, high-effort): Most of the time in constructing a matrix goes into looking a monomial up to find the corresponding column index. Find a way to improve the code for this so that it goes faster both serial and in parallel. Perhaps use SSE instructions? (this will likely require changing MonoMonoid, which won't be easy). Project (high-effort, high-difficulty): There is no limit on how much memory might be required to store the constructed matrix. Find a way to construct it in pieces so that the memory use can be bounded. This should not impact performance for matrices that fit within the required memory and it should not slow down computations for large matrices too much. Project (high-effort, high-difficulty): Matrix construction speed does not scale perfectly with the number of cores. Determine the reason(s) for this and fix them to get perfect scaling up to, say, 20 cores. Perhaps use something like Intel VTune, which I hear is great for this sort of thing. *** mathicgb/F4MatrixProjection.hpp .cpp This class is used by F4MatrixBuilder2 for the second step where the matrix is split into parts ABCD. F4MatrixProjection is fed all of the sub-matrices built by the parallel cores in the construction step and it is told what all the columns are and which ones are left and which ones are right. Then it builds a QuadMatrix, which is the 4 matrices A,B,C,D. The first thing done is to figure out the necessary permutation of rows. Note that it is really up to this class itself to choose which rows are top/bottom, since that does not change the row echelon form of the matrix. The only restriction is that a row with no entry on the left must be on the bottom and that every left column must have exactly one top row with the leading non-zero entry in that row - or equivalently, the upper left matrix must be upper-triangular with no zeroes on the diagonal. The row permutation constructed chooses the sparsest rows that it can as the top rows, since those are going to be used multiple times for reduction. After the row permutation has been constructed, it is just a question of going through every row in the order that the permutation dictates and split it into the left/right sub-matrices. This process has a memory issue in that it copies the matrix to permute the rows and this doubles memory use. We cannot free the rows that have already been copied because the memory for rows is allocated in blocks and we cannot free a block until all rows in that block are copied - and the rows are being copied in some arbitrary order depending on the row permutation. Doubling memory here is bad because the memory required to store the matrix can dwarf the memory otherwise used by Buchberger's algorithm, which is already a lot of memory. Project (medium-effort, high-difficulty): Find a way to apply the row permutation and left/right splitting without doubling memory use. This might be achieved by copying several times. The difficulty is in finding a way to do this that inflates memory use only a little (instead of doubling it) while also getting excellent performance. One idea would be to use a harddisk for temporary storage. If the whole thing cannot be done quickly, it might make sense only to use this technique if memory would have been exhuasted by doubling the memory used - in that case any amount of slow-down is worth it, since otherwise the computation cannot proceed (at least not without using virtual memory, which is going to be quite slow most likely). Project (high-effort, high-difficulty): The left/right and top/bottom split is not parallel. Make it parallel. The obvious way to do this is to construct the rows of the output matrices in blocks and to have each thread do its own block. The easiest way is to do A,B,C,D in parallel, but this parallelim can be done also on sub-matrices of A,B,C,D. Project (high-effort, high-difficulty): For best speed on matrix reduction, we do not just want to split into left/right and top/bottom, we want to split the whole matrix into blocks of a cache-appropriate size, while also (probably) doing the top/bottom left/right thing. This will require a redesign of how the program handles these submatrices. Project (high-effort, high-difficulty): There is also a difficult question of how to sub-divide into cache-appropriate blocks on sparse matrices, since sub-matrices in a sparse matrix will vary widely in memory size, so a regular grid of sub-matrices might not be optimal - some sub-matrices might need to be bigger than others in order to get each sub-matrix to take up about the same amount of memory. The literature might have something to say about this. *** mathicgb/F4MatrixReducer.hpp .cpp This is where the reduction of the matrices happens. For the reduction of the left part of the matrix, each bottom row is reduced in parallel. An active row is copied into a dense format and then the sparse top rows are used to reduce it. This is good because the linear algebra of applying a sparse reducer to a dense reducee can be implemented well on a computer. (see slides) Using delayed modulus is an important optimization here. (see slides) After this we still need to interreduce the rows of the bottom right part of the matrix, which can take a significant amount of time. This is done by choosing a subset of rows with new pivots and reducing the other rows with respect to these rows, which can be done in parallel. This step is repeated until all rows become pivot rows or zero rows. Part of the problem here is that selecting the set of pivot rows introduces synchronization points so that there might be a lot of waiting for the last core to finish, because there is a wait at the end of every step. Since reducees need to be converted into dense format and then back, there is either a very high memory consumption (for keeping everything dense, which is the way it's done now) or there is a lot of overhead for converting between dense and sparse formats. Schrawan made a non-parallel implementation that has only 1 active row at a time, so there is no explosion in memory use when a very sparse lower right matrix needs to be reduced. The skeleton of the algorithm used for that implementation is also what I'd recommend for a future parallel implementation using atomics. Project (high-difficulty, medium effort): Schrawan finished his code, but he never got it into MathicGB. Get him to put it into MathicGB. Project (high-difficulty, medium-effort): Implement a parallel reduction without synchronization points using atomics. Cores would be competing for who gets to have a pivot in a given column and they would keep going until their active row is either reduced to zero or it becomes a pivot. Project (high-difficulty, high-effort): Scour the literature to find a good parallel algorithm. Implement it. See if it is better. Possibly use different algorithms depending on the sparsity of the matrix. Some lower right matrices are very dense and some are very sparse and some are in-between. Project (high-difficulty, high-effort): Use vector intrinsics (SSE and it's like) to speed up the matrix reduction. Project (high-difficulty, high-effort): Use GPU's to speed up the matrix reduction. Project (medium-difficulty, high-effort): Try out BLAS for this purpose. Try out other already-implemented libraries that might be useful. There is also the sparse blas. Can that be used? Project (medium-difficulty, high-effort): The current implementation is for 16 bit primes. Make it work/optimize it for 8 bits and 32 bit primes as well. There is a C++ library for doing lots of modulus operations by a fixed (but not compile-time constant) integer using fancy bit tricks, but for the life of me I cannot find this library's website again - something like that might be quite useful, since higher bit primes is going to decrease the usefulness of the delayed modulus technique. *** mathicgb/F4ProtoMatrix.hpp .cpp This class is used by F4MAtrixBuilder2 to store the sub-matrices constructed by each core during the initial matrix construction step. Memory is stored in large std::vector's. There is a slight special thing about storing the coefficients. If a row in the matrix is m*f for m a monomial and f a basis element, then there is no reason to store the coefficients, since the coefficients will be just the same as the coefficients of f. We can instead just refer to f. If a row is mf-ng, on the other hand, then we do need to store the coefficients. F4ProtoMatrix keeps track of this, so that some rows have their coefficients stored as a reference to a polynomial and other rows have their coefficients stored explicitly within the F4ProtoMatrix itself. Project (medium-difficulty, medium-effort): See if it wouldn't be faster to store the sub-matrices in fixed-size blocks of memory instead of in std::vector. push_back on std::vector is O(1), but the constant is greater than for allocating reasonably sized blocks and using those. There is a tricky special case if a very large row uses more memory than the block size. This would decrease memory use, too, since vector wastes up to half of its memory and these vectors can be huge. *** mathicgb/F4Reducer.hpp .cpp This class exposes the matrix-based reduction functionality as a sub-class of Reducer. So the rest of the code can use F4 without knowing much about it. F4Reducer can write out matrices, but only after splitting into left/right and top/bottom. Project (low-effort, low-difficulty): A lot of the logging here is done using tracingLevel. Move that logging to use the MathicGB logging system. *** mathicgb/FixedSizeMonomialMap.h This is a parallel atomic-based hash table that maps monomials to a template type T, generally an integer. The hash table is chained because it needs to refer to monomials anyway which requires a pointer, so there is no reason not to use chaining. The next pointer in the chain and the value is stored right next to the monomial in memory. The hash table is fixed size in that it cannot rehash or change the number of buckets. The hash table cannot change its size because of the nature of the paralellism used - there is no way to force all the cores to be aware of the new rehashed hash table (it's a bit like read-copy-update used in the Linux kernel, except that there's no fixed amount of waiting that will make it safe to deallocate the old memory). MathicGB never the less does achieve rehashing and growing the hash table, just not directly within a single FixedSizeMonomialMap - see MonomialMap. A lot of effort went into making the following operation as fast as possible: findProduct(a,b): return the value of the entry corresponding to a*b. where a,b are monomials. That's because that is where most of the time for matrix construction goes. Most of the time for matrix construction still goes there despite significant gains in speeding this up. (see slides) Project (high-effort, high-difficulty): Find a way to significantly speed up the findProduct operation. Perhaps SSE can help, or some kind of cache prefetch instructions. Or a change to memory layout. Project (low-effort, low-difficulty): This file is for some reason called .h instead of .hpp. Fix that. Project: Get an expert on parallel algorithms to review this part of the code. Perhaps something can be improved? *** mathicgb/io-util.hpp .cpp This file collects a lot of IO and toString related functionality. This functionality has been superseded by the MathicIO class. Project (medium-effort, low-difficulty): Migrate the remaining uses of io-util over to use MathicIO and then remove io-util. *** KoszulQueue.hpp Used to keep track of pending Koszul syzygy signatures in the signature basis (SB) algorithm. SB keeps a priority queue (ordered queue) of certain Koszul signatures that are greater than the current signature -- see the SB paper. *** LogDomain.hpp .cpp *** LogDomainSet.hpp .cpp These files form the MathicGB logging system. A LogDomain is a named area of logging that can be turned on or off at runtime and at compile time. A logger that is turned off at compile time emits no code into the executable and all the code that writes to that logger is also removed by the optimizer if it is written in the correct way. Use the logging macroes to ensure proper use so that compile-time disabled LogDomains properly have zero overhead. LogDomains can be turned on and off at compile time and at runtime individually. Here logging means both outputting messages to the screen right away and collecting statistics for showing later summary information about the computation. See these files for further details. Compile-time enabled loggers automatically register themselves at start-up with LogDomainSet::singleton(). LogDomainSet is a singleton that keeps track of all the logging domains. Project (low-effort, medium-difficulty): support turning all loggers off globally at compile time with a single macro, regardless of their individual compile-time on/off setting. This would allow an easy way to measure the overhead of the logging. Project (high-effort, medium-difficulty): replace all logging based on trace-level or adhoc-counters with use of the MathicGB logging system. *** mathicgb.h This is the entire library interface of MathicGB. It's full of documentation, so go read the file if you want to know how the library interface works. Clients of the library should not #include any other file from MathicGB. This is the only file that's supposed to be called .h instead of .hpp, since it is included from the outside and .h is the customary header even for C++ headers. Project(medium-effort, medium-difficulty): Expand the library interface to expose the ability to compute signature bases. Both as in getting a signature basis output and as in using a signature basis algorithm to compute a classic Groebner basis. Project(medium-effort, medium-difficulty): This header hides all of its implementation using the pimpl pattern. It would be nice if the header and the implementation were so separate that you could even compile on different compilers and still have work. That requires an interface that uses extern "C" as calling convention. So get the separation to that level. Though I'm not actually so knowledgeable about this matter, so first do some research on this kind of thing to figure out what makes sense and then do that. *** MathicIO.hpp This file collects all IO-related functionality for MathicGB objects. This is reasonable since most of the IO-relevant classes are composites whose IO requires IO of its pieces. So putting it together lowers compile time and avoids cluttering up all the various classes with IO code. Project (medium-effort, low-difficulty): The input and output code is completely separate, so it was silly of me to put it on the same class. Separate this class input MathicInput and MathicOutput. That would allow each class to keep a bit of state - the file or ostream/istream that is being written to/read from. The state of MathicInput would be a Scanner. The state of MathicOutput would be at first an ostream. However, std::ostream is extremely slow, so you'd probably want to migrate that to a FILE*. To be more fancy, you could keep a largish buffer and then allow output of that buffer to either an ostream or a FILE*. Both FILE* and ostream has per-operation overhead, so this will likely be the fastest approach anyway - and it mirrors what Scanner does. Project (high-effort, medium-difficulty): The current file format is a complete mess and it's not documented. It shouldn't be too hard to figure out from looking at the IO code what the format is. Come up with a much better format and implement it. The problems with the current format include that you can have at most 52 variables and the way that the monomial order is specified is weird. If this is too much work, at least document what the current format is, weird as it may be. *** mathicgb/ModuleMonoSet.hpp .cpp Allows operations on the ideal generated by a set of module monomials. Currently used for signatures. This is a virtual interface with several implementations based on different mathic data structures. The templates are instantiated in the .cpp file to hide them from the rest of the code. The implementations are based on StaticMonoLookup. *** mathicgb/MonoLookup.hpp .cpp Supports queries on the lead terms of the monomials in a PolyBasis or a SigPolyBasis. This is a virtual interface that is implemented in the .cpp file using templates based on several different mathic data structures. The implementations are based on StaticMonoLookup. Project (medium-difficulty, medium-effort): It's a mess mixing classic GB functionality, signature functionality and general monomial lookup functionaliy like this. Find a good way to disentangle these things. *** mathicgb/MonomialMap.hpp A concurrent/parallel wrapper around FixedSizeMonomialMap. If the current FixedsizeMonomialMap gets too full, a new one is created and the nodes from that one are cannibalized into the new one, but the old table is still kept around. This way a core that is still using the old table will not get memory errors, that core just might fail to see a monomial that is supposed to be there. The matrix construction code is written so that not finding a monomial causes synchronization followed by a second look-up. That second look-up will identify the most recent hash table and use that for the lookup, so rehashing can be done safely and quickly in this way. The only real penalty is that all the old hash tables have to be kept around, but that is not much memory. *** MonoMonoid This class implements monomials and ordering on (monic) monomials. It is quite complicated but the interface is nice so all the complexity is hidden from the rest of the program. The nasty stuff is handled once here and then no where else. The interface is supposed to make it impossible to create a mal-formed monomial, at least unless you do a cast or refer to deallocated memory. The eventual idea is to make everything a template on this class so that the monomial representation can be radically changed at run-time to suit a given computation with no overhead. So no other part of the program should have any knowledge of how monoids are represented, which is already almost (maybe even fully?) the case. The memory layout of a monomial depends on template parameters to MonoMonoid as well as on the number of variables, the monomial ordering being used and the module monomial ordering being used. It would take a long time to explain the whole thing and it is all already documented well in the file, so go there for the details. Changes to this class should be done with care, in part because it's very easy to introduce bugs and in part because the code is carefully written and almost all of it is performance critical - any change is quite likely to make the program slower, so run lots of benchmarks after changing something. Project(high-effort, high-difficulty): Make everything that interacts with monomials a template on the Monoid. This has already been started, by giving each class a typedef for Monoid - in future, this will become the template parameter. The trick is to use virtual interfaces to avoid the problem LELA has where any change to any part of the program (almost) requires the whole program to be re-compiled. Project(high-effort, high-difficulty): Implement an alternative Monoid that uses SSE instructions for fast monomial operations. The tricky part here will be memory alignment and choosing the right representation in memory. Then try that monoid out in benchmarks and get a speed-up for inputs that cause a lot of monomial computations. Project(high-effort, high-difficulty): Implement an alternative monoid that is specialized for 0-1 exponents in the presence of the equations x^2=x, so that each exponent only requires 1 bit. Document a nice speed-up on inputs with 0-1 exponents. Project(high-effort, high-difficulty): Make monoids that differ only in their template boolean parameters (StoreHash, etc.) share part of the same state (in particular, the ordering matrix), since it is the same anyway. The trick is to do this without impacting performance negatively. Project(high-effort, high-difficulty): Implement an alternative monoid that uses a sparse representation so that only non-zero exponents are stored. Document a nice speed-up on inputs where most exponents are zero. The challenge here is that the monomials are no longer all the same size. I've attempted to write the rest of the program without an assumption of same-size monomials. The main problem will be MonoPool. You'll want to eliminate as many uses of that as possible (I've tried not to use it for new code) and then perhaps just eat the waste of memory for the remaining few uses. Project(high-effort, high-difficulty): Implement an alternative monoid that is optimized for toric/lattice ideals. These are binomial saturated ideals where x^a-x^b can be represented with the single vector a-b. Compare to 4ti2. Can we beat them? Project(high-effort, high-difficulty): Have monoids for 8 bit, 16 bit, 32 bit, 64 bit. When an exponent overflow occurs anywhere in the program, take the current state of the computation and then transfer that into the equivalent monoid with next-higher precision of exponents. Project(high-effort, high-difficulty): As previous project, but also include arbitrary precision exponents as the final monoid that can handle any size exponent. This sort of thing becomes relevant for some toric ideal computations and it's why 4ti2 has a build with arbitrary precision exponents. The challenge here is that exponents now become heavy resource handles - I'm not sure what making that change will require. Copying an exponent suddenly goes from cheap to very expensive. Project(high-effort, high-difficulty): Currently it is allowed to mix module monomials and monomials. They are not different types. MonoMonoid already has a bool parameter intended to make this separation (HasComponent). However, the rest of the code doesn't observe the distinction, so HasComponent cannot be enforced. Fix that. Project(high-effort, high-difficulty): Make a MonoMonoid that uses an internal virtual interface so that it can implement any monoid what-so-ever. Then expose that functionality through the library interface, so that external clients can run Groebner basis computations on their own monoids. This will likely be slow, but that's OK - if that's not acceptable, then just don't use this monoid. *** mathicgb/MonoOrder.hpp Class used to describe an monomial order and/or a module monomial order. Use this class to construct a monoid. The monoid does the actual comparisons. Module monomials must be preprocessed by MonoProcessor - otherwise the ordering may not be correct. MonoProcessor offers additional parameters for making orders. *** mathicgb/MonoProcessor.hpp Does pre- and post-processing of monomials to implement module monomial orders not directly supported by the monoid. This is the case for Schreyer orderings and for changing the direction of which component e_i is greater. You need to use this class if you are doing input or output of module monomials, since the external world will not know or want to know about the transformations used to achieve these orderings. *** mathicgb/mtbb.hpp A compatibility layer for tbb. tbb stans for Intel thread building blocks and it's a good library for implementing parallel algorithms. If we are compiling with tbb present, then the classes in the mtbb namespace will simply be typedefs for the same classes as in the tbb namespace. However, if we are compiling without tbb (so without parallelism), then these classes will be trivial non-parallel implementations that allows MathicGB to work without tbb being present. TBB doesn't work on Cygwin, so that is at least one good reason to have this compatibility layer. This only works if all uses of tbb go through the mtbb namespace, so make sure to do that. Project (high-effort, high-difficulty): get TBB to work on Cygwin and get an official TBB-Cygwin package into Cygwin. *** mathicgb/NonCopyable.hpp Derive from NonCopyable to disable the compiler-generated copy constructor and assignment. In C++11 this can be done with deleted methods, but support for that is not universal, so use this instead for now. *** mathicgb/Poly.hpp Poly stores a polynomial. This was originally a large and somewhat complicated class, but not so much any more since PrimeField and MonoMonoid now offer encapsulation for everything having to do with how coefficients and monomials are to be handled. Poly is now mostly just a thin layer on top of those abstractions. *** mathicgb/PolyBasis.hpp Stores a basis of polynomials. Designed for use in Groebner basis algorithms - PolyBasis offers functionality like finding a good reducer for a monomial. *** mathicgb/PolyHashTable.hpp A hash table that maps monomials to coefficients. Used in classic polynomial reducers. The implementation is very similar to MonomialMap except that this hash table is not designed for concurrent use. *** mathicgb/PolyRing.hpp Represents a polynomial ring. Deals with terms - a monomial with a coefficient. It used to be that this class handled everything to do with coefficients and monomials so it has a very large interface related to all that because some of the code still uses that old interface. It is supposed now to be just the combination of a field and a monoid - eventually it would become a template on those two. In future Poly might become a nested class on PolyRing, just like Mono is a sub-class of MonoMonoid. I'm not sure if it is a good idea. The question is if it would ever make sense to use two different representations of polynomials from the same PolyRing. I think probably not, but I'm not sure. Project (high effort, medium difficulty): Get rid of all the remaining code that uses the coefficient and monomial interface of PolyRing and migrate those to use MonoMonoid and PrimeField. Then clean up the PolyRing header to remove all that stuff that is then no longer needed. This would involve moving code to use NewConstTerm and then please rename that to just ConstTerm and make it a nested type of PolyRing that everything uses. *** mathicgb/PrimeField.hpp Implements modular arithmetic. Is to coefficients what MonoMonoid is to monomials. Ideally, it would be possible to swap in a different coefficient field just by implementing an alternative to PrimeField. For example computations over Z or Q or something more complicated would then be possible. This is a more far-off feature and the code base is much less prepared for this than it is for alternative monoids. On the other hand, less of the code does much with coefficients than monomials, so it might not be that bad. Project (high-effort, low-difficulty): A lot of code still uses the PolyRing interface for coefficients. Move that code to use PrimeField and then remove the implicit conversions between PrimeField::Element and the underlying coefficient type. The idea here is that it should be impossible to use coefficients incorrectly by mistake. For example it is very easy to just add two coefficient using + by mistake, which is bad because then you do not get the modulus and you might get an overflow. Project (high-effort, high-difficulty): Have modular coefficient fields with 8, 16, 32 and 64 bits. Then use the appropriate size at run-time for the given modulus. Right now we use a 32 bit integer, yet the matrix-based reducer only supports 16 bit primes, leaving half the coefficient bits wasted for any computation using the matrix-based reducer. Project (high-effort, high-difficulty): Implement a coefficient field over Z or Q and use that. Project(high-effort, high-difficulty): Make a Field that uses an internal virtual interface so that it can implement any coefficient field what-so-ever. Then expose that functionality through the library interface, so that external clients can run Groebner basis computations on their own field implementations. This will likely be slow, but that's OK - if that's not acceptable, then just don't use this field. *** mathicgb/QuadMatrix.hpp .cpp A struct that stores 4 matrices, top/left and bottom/right, and left/right column monomials that describe what monomial corresponds to each column (see ABCD paper and slides). There is also some functionality, such as printing statistics about the matrices and doing IO of the matrices. This class is a mess. It's written like a pure data struct just keeping a few fields but it has extra functionality. It keeps lists of column monomials and a monoid even though it is used in places where there is no monoid. Project(low-difficulty, medium-effort): Encapsulate the 4 matrices instead of having them be public fields. Then move the vectors of column monomials and the PolyRing reference to some other place so that a QuadMatrix can be used in contexts where there are no monomials - such as when reading a matrix from disk. Also move the IO to MathicIO. *** mathicgb/QuadMatrixBuilder.hpp Used by F4MatrixBuilder to do the splitting into left/right and top/bottom during matrix construction. Not a lot of code here. *** mathicgb/Range.hpp Introduces basic support for the range concept. A range is, conceptually, what you get when you have a begin and an end iterator. Combining these together into one thing allows a more convenient coding style and this header makes that easy. This also combines very well with the C++11 range-based for loop, which allows iteration through a range object. See the documentation in the file for more details on what this is all about. Project(high-difficulty, high-effort): Get on the C++ standard committee working group for ranges and get them to put better support for ranges into the standard library as quickly as possible! *** mathicgb/Reducer.hpp .cpp This is a virtual interface that encapsulates polynomial reduction. It allows the rest of the code to use any of many different reduction implementations without having to know about the details. *** mathicgb/ReducerDedup.hpp .cpp *** mathicgb/ReducerHash.hpp .cpp *** mathicgb/ReducerHashPack.hpp .cpp *** mathicgb/ReducerHelper.hpp .cpp *** mathicgb/ReducerNoDedup.hpp .cpp *** mathicgb/ReducerNoDedup.hpp .cpp *** mathicgb/ReducerPack.hpp .cpp *** mathicgb/ReducerPackDedup .cpp These implement various ways of doing classic polynomial reduction. They register themselves with Reducer using a global object, so if you change one of these files, only that single file will be recompiled. The same is true of F4Reducer. Project(high-difficulty, high-effort): Improve these reducers. The fastest one is ReducerHash. Make it faster! :) *** mathicgb/Scanner.hpp .cpp A class that is very convenient for parsing input, much more so than std::istream. It is also faster than using std::istream or FILE* directly. It can accept (buffered) input from either a std::istream or a FILE*. All text input should go through a Scanner and for a given input it should all go through the same scanner since the scanner keeps track of the line number for better error messages - that only works if no part of the input is read from outside of the scanner. *** mathicgb/ScopeExit.hpp Implements a scope guard. Very convenient for ad-hoc RAII needs. Naming the scope guard is optional. Example: FILE* file = fopen("file.txt", "r"); MATHICGB_SCOPE_EXIT() { fclose(file); std::cout << "file closed"; }; // ... return; // the file is closed Example: v.push_back(5); MATHICGB_SCOPE_EXIT(name) {v.pop_back();}; // ... if (error) return; // the pop_back is done name.dismiss(); return; // the pop_back is not done *** mathicgb/SignatureGB.hpp Implements the SB algorithm. Project(medium-effort, low-difficulty): Wait with inserting the input basis elements into the basis until their signature becomes <= the currrent signature. Then regular reduce them at that point. This ensures that the basis is regular auto reduced at all times without doing any auto reduction - otherwise it isn't. This actually might even be a correctness issue for the case where the input basis is not already top auto reduced! Project(high-effort, high-difficulty): Combine SB with matrix-based reduction. Project(high-effort, medium-difficulty): Migrate all the code here from using ad-hoc statistics and logging to using the MathicGB logging system. Project(high-effort, high-difficulty): Implement better support for incremental module orderings ("module lex" or "component first"), especially in the case where we only want a Groebner basis and not a signature Groebner basis. Between incremental steps, it would be possible to reduce to a Groebner basis and possibly also a win to dehomogenize and re-homogenize. This is likely a huge improvement for some examples. *** mathicgb/SigPolyBasis.hpp .cpp Stores a basis of polynomials that each have a signature. Designed for use in signature Groebner basis algorithms. *** mathicgb/SigSPairQueue.hpp .cpp A priority queue on S-pairs where the priority is based on a signature as in signature Grobner basis algorithms. The class is not responsible for eliminating S-pairs or doing anything beyond order the S-pairs. *** mathicgb/SigSPairs.hpp .cpp Handles S-pairs in signature Grobner basis algorithms. Responsible for eliminating S-pairs, storing S-pairs and ordering S-pairs. See SB paper. *** mathicgb/SPairs.hpp .cpp Stores the set of pending S-pairs for use in the classic Buchberger algorithm. Also eliminates useless S-pairs and orders the S-pairs. Uses a novel S-pair elimination criterion based on minimum spanning trees in a certain graph. Should be slightly better than the Gebaeur-Moeller criterion. See description at end of online appendix to SB paper. Project(medium-effort, high-difficulty): There's a tricky issue here. SPairs computes the lcm of the leading term of components of an S-pair in order to figure out if that S-pair can be eliminated. It is not necessary to compute the hash value or the degree (=ordering data) of the lcm to figure that out. So it uses a monoid instantiated not to compute these things. However, the monomial lookup data structure used is for the usual monoid that does have these things. So the types don't match. These types are layout-compatible, so I fix this currently by breaking encapsulation and just casting from one type to the other, creating a monomial with invalid hash and degree information - though that works out because the lookup data structure never looks at those field. This is not a good solution. A good solution would be to expose the layout-compatibility and allow conversion of references between the monoids so that the lookup data structure could advertise just an interface based on the bare monoid (no pre-computed hash or ordering data) and then that interface could be used directly on monomials from the usual monoid via (possibly implicit) conversions of MonoidWithManyField::ConstMonoRef to MonoidWithFewerFields::ConstMonoRef. Or find a better solution! *** mathicgb/SparseMatrix.hpp Stores a matrix in sparse format. Column indices are stored separately from scalars. Column indices and scalars are stored in large blocks of memory and a matrix is a sequence of such blocks. The row metadata (where is the scalars and indices for this row?) is stored in a single std::vector. It was a significant speed-up when I moved to this block structure from the previous design which stored scalars in one huge std::vector and indices in another huge std::vector. This is the default class used to store matrices. For example a QuadMatrix consists of 4 SparseMatrices. *** mathicgb/StaticMonoMap.hpp A template class for implementating many monomial look-up data structure operations. Based on mathic data structures and which one you want is a template parameter. Used as the underlying implementation for most (all?) of the monomial lookup data structures in MathicGB. *** mathicgb/stdinc.h This file is the first file included by all .cpp files in MathicGB. Therefore everything in it is available everywhere. This file contains a lot of macroes and some typedefs that should be available everywhere. Project(medium-effort, low-difficulty): This file should be named stdinc.hpp, not stdinc.h. Rename it. Project(medium-effort, low-difficulty): Pre-compiled headers should speed up compilation of MathicGB tremendously. Especially putting memtailor and mathic in a precompiled header should help. Probably also MonoMonoid, PrimeField, PolyRing and parts of the STL. Set up support for this in MSVC and GCC. Half the work is already done since stdinc.h can be the precompiled header - it's already included as the first thing everywhere. *** mathicgb/TypicalReducer.hpp .cpp All the non-matrix based reducers use the same classic polynomial reduction high-level algorithm. This class implements that high-level algorithm and then a sub-class can specialize the detailed steps, thus sharing a lot of code between the various reducers. *** Unchar.hpp std::ostream and std::istream handle characters differently from other integers. That is not desired when using char as an integer. Use Unchar and unchar() to cast integers to a different type (short) if they are char. *** test/* These are unit tests. Project(high-effort, medium-difficulty): Find things that are not currently tested and add tests for them. *** cli/* This is for the command line interface. Project (low-effort, low-difficulty): Emit a better and more helpful message when running mgb with no parameteres. At a minimum, point people to the help action. ***** Other projects Project (medium-effort, medium-difficulty): The leading terms of monomials in the basis are not placed together in memory. Placing them together in memory might improve cache performance for monomial queries. Project (high-effort, low-difficulty): In a lot of places 0 is used to indicate the null pointer. Replace all of those zeroes by the proper C++11 keyword: nullptr. Project (medium-effort, medium-difficulty): The matrix based reducer checks overflow of exponents (using the "ample" concept from MonoMonoid). The other reduceres do not. Fix that. What is the performance impact? Project (medium-effort, high-difficulty): The tournament trees in mathic are non-intrusive. An intrusive tournament tree should be faster. Try that. Project (high-effort, low-difficulty): In some places in MathicGB and in lots of places in memtailor and mathic, methods are named getFoo(). Change that to just foo(). Also, mathic and memtailor use _ as a prefix to indicate a member variable. That's a terrible idea, since the standard reserves names starting with an underscore to be used only by the standard library implementation. (well, strictly speaking the prefixes __ and _ followed by an upper case letter, but still). Project (medium-effort, medium-difficulty): memtailor, mathic and mathicgb download and compile gtest automatically if gtest is not found on the system. mathicgb should do the same thing with memtailor and mathic. That would ease installation greatly. Project (medium-effort, medium-difficulty): There are a lot of comments using /// all over, which indicates to doxygen that this is a comment that should be included as part of the documentation. However, there is not a doxygen makefile target! Make one. Project (medium-effort, medium-difficulty): The library interface should have an option to get a fully auto-reduced (including tail-reduced) Groebner basis at the end. Project (medium-effort, medium-difficulty): The makefile made by mathicgb/build/setup/make-Makefile.sh has a target called ana. This stands for analysis. What it does is that it runs gcc with all warnings that I could find anywhere turned on and it treats warnings as errors. memtailor, mathic and mathicgb should build with this target without any warnings or errors. That's currently not the case, so that should be fixed. Project (medium-effort, medium-difficulty): Make a makefile target like ana, but targeting clangs static analysis tool(s). Then silence all the issues that come up. Project (medium-effort, medium-difficulty): Files should include what they use and no more than that. They should also prefer forward declarations when that is sufficient. This eases the development process as it avoids errors from missing headers and it avoids unnecessary recompilations. Maintaining the invariant that every file includes exactly what it needs and no more isn't practical to do by hand. The tool include-what-you-use flags every missing header, every superfluous header and every include that could be replaced by a forward declaration. http://code.google.com/p/include-what-you-use/ . Make a makefile target like ana that runs include-what-you-use over everything. Project (high-effort, medium-difficulty): All the Groebner basis implementations are based on giving each basis element an index and then maintaining data structures that use those indices. As basis elements become top-reducible, some of those indices fall out of use (retired). If there are many retired indices, then that causes overhead. For example the bit-triangle used to keep track of S-pairs uses O(n^2) space where n is the number of indices - retired indices still use just as much space. This can be fixed by reindexing - map all the active indices to smaller indices so that there are no gaps left for the retired indices - it's like they were never there. Update all data structures simultaneously to use these new indices. This could be done if, say, 1/2 of the indices become retired, or whatever is a suitable fraction. Project (high-effort, high-difficulty): MathicGB uses local memory threaded parallelism. Find a way to do computations also in a distributed manner and get a good speed-up. Probably the matrix reduction is the best first place to make this happen. Project (medium-effort, medium-difficulty): MathicGB currently uses enums to identify the various different reducers and data structures. These integer ids are even exposed in the command line interface, so you say for example "give me reducer 24". This is not a great design. Instead, give each reducer a string name and let the command line interface use those. Enable unique prefix matching just like is done for action names. Inside MathicGB, get rid of the enums entirely. Avoid passing around strings to desribe the desired reducer, for example. Instead just pass the actual reducer around. Project (high-effort, high-difficulty): Let the matrix-based reducer run on modules. Project (high-effort, high-difficulty): Let MathicGB keep track of the module representation of it's calculations - that is, how the output basis is represented in terms of the input basis. Calculate syzygies using this information. Project (medium-effort, medium-difficulty): Get MathicGB to run on Clang. It might do that already. I don't know. Project (medium-effort, medium-difficulty): gcc has link time optimization (lto) and profile-drive optimization. It can lead to significant improvements in speed and we are not using those. Set up a way to use these and measure the performance improvement. Is it worth the hassle? Project (high-effort, medium-difficulty): Benchmarking has so far been quite ad-hoc. Set up a good battery of tests, both of ideals and matrices. Maybe get external people involved too. Maybe have a server that runs benchmarks and pulls from git each day and graphs the results. Project (medium-effort, medium-difficulty): Get a Sage interface to MathicGB. Project (high-effort, high-difficulty): Popularize MathicGB. Get everyone to know about it. Attract more developers. Project (high-effort, medium-difficulty): Write a nice user's manual. Project (medium-effort, medium-difficulty): There are currently no tests that directly invoke the command line interface. Set some up. Project (medium-effort, medium-difficulty): Reducer is a virtual interface and it's intended to be used via unique_ptr handles. Not too bad, but value semantics would be nicer. Try this sort of technique out: http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil The idea here is to push the virtualness inside the class so that it becomes an implementation detail instead of something that is exposed to clients of the class. Exactly how this should be done for Reducer, evaluating if this is even a good idea and figuring out if this idea should be applied to widely to other instances of polymorphism in MathicGB is part of the project. Project (medium-effort, medium-difficulty): MathicGB was first written before C++11. So to move data around without copying, we used std::auto_ptr. Once we started using C++11, all of those were then replaced with std::unique_ptr. However, for classes with move semantics, we can now just move them around using those move semantics without wrapping things in a std::unique_ptr. It's an unnecessary indirection. Find all unnecessary std::unique_ptr's and get rid of them. Look for std::unique_ptr where T is a non-virtual class with move semantics - that's a good clue that probably std::unique_ptr isn't doing anything useful there. The main example of this is std::unique_ptr, which appears in several places. mathicgb-master/doc/mgb.1000066400000000000000000000011161311555162500155240ustar00rootroot00000000000000.TH MGB "1" "April 2015" .SH NAME Mathicgb: \- Compute (signature) Groebner bases using the fast data\%structures from mathic. .SH DESCRIPTION .HP gb \- Compute a Groebner basis. .HP help \- Return information about the command line interface. .HP matrix \- Perform matrix computations. .HP siggb \- Compute a signature Groebner basis .SH AUTHORS Mathicgb was written by Bjarke Hammersholt Roune and Michael Stillman . This manual page was written by Doug Torrance for the Debian project (but may be used by others). mathicgb-master/doc/slides.pdf000077500000000000000000033664301311555162500166760ustar00rootroot00000000000000%PDF-1.5 % 10 0 obj << /S /GoTo /D [11 0 R /Fit] >> endobj 39 0 obj << /Length 1404 /Filter /FlateDecode >> stream xXKs6W(̈́,fRN~dzh{VkJ$7Szw %ʱ7n QƷ>C϶v3>~ĹZstM9 ,%TiP2mhJԯ+Y%I,)"BE$h\#"Jq`JͮN6T%oY|pMc$A˼mnu+"vwuMyJ}- w ۓ:y$|v$I`hns&a<*ѵ*͂!68_\yj~ aG{p{~7T40*, SmΦN>QDVQ \ 5IKP 2Ik_P_4v`2pC?8r]oĀ: NUxl:cW:'K*"f&F~ OΚ04P=8Xu7 G( ?9(l?\4ZDc2#*QH.-~F$|7^Rx1Pi^ 1SJ){i.|ASOs"Wи6p!M) l+[)i}eSB*ӡi}eSn&Ք\ϾcҰrn9BVgh뽽 !.2e87do㓉0v7)[m8틩m'q+"//Nm6m.n.ꐋUsE0_{5_ endstream endobj 11 0 obj << /Type /Page /Contents 39 0 R /Resources 38 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 46 0 R /Annots [ 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R ] >> endobj 12 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 362.835 3.985] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 47 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 47 0 obj << /Shading << /Sh << /ShadingType 2 /ColorSpace /DeviceRGB /Domain [0 1] /Coords [0 0.0 0 3.9851] /Function << /FunctionType 2 /Domain [0 1] /C0 [1 1 1] /C1 [0.5 0.5 0.5] /N 1 >> /Extend [false false] >> >> /ProcSet [ /PDF ] >> endobj 15 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 8 8] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 48 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 48 0 obj << /Shading << /Sh << /ShadingType 3 /ColorSpace /DeviceRGB /Domain [0 1] /Coords [4.00005 4.00005 0.0 4.00005 4.00005 4.00005] /Function << /FunctionType 2 /Domain [0 1] /C0 [0.5 0.5 0.5] /C1 [1 1 1] /N 1 >> /Extend [true false] >> >> /ProcSet [ /PDF ] >> endobj 16 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 16 16] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 49 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 49 0 obj << /Shading << /Sh << /ShadingType 3 /ColorSpace /DeviceRGB /Domain [0.0 8.00009] /Coords [8.00009 8.00009 0.0 8.00009 8.00009 8.00009] /Function << /FunctionType 3 /Domain [0.0 8.00009] /Functions [ << /FunctionType 2 /Domain [0.0 8.00009] /C0 [0.5 0.5 0.5] /C1 [0.5 0.5 0.5] /N 1 >> << /FunctionType 2 /Domain [0.0 8.00009] /C0 [0.5 0.5 0.5] /C1 [1 1 1] /N 1 >> ] /Bounds [ 4.00005] /Encode [0 1 0 1] >> /Extend [true false] >> >> /ProcSet [ /PDF ] >> endobj 14 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 5669.291 8] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 50 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 50 0 obj << /Shading << /Sh << /ShadingType 2 /ColorSpace /DeviceRGB /Domain [0.0 8.00009] /Coords [0 0.0 0 8.00009] /Function << /FunctionType 3 /Domain [0.0 8.00009] /Functions [ << /FunctionType 2 /Domain [0.0 8.00009] /C0 [1 1 1] /C1 [0.5 0.5 0.5] /N 1 >> << /FunctionType 2 /Domain [0.0 8.00009] /C0 [0.5 0.5 0.5] /C1 [0.5 0.5 0.5] /N 1 >> ] /Bounds [ 4.00005] /Encode [0 1 0 1] >> /Extend [false false] >> >> /ProcSet [ /PDF ] >> endobj 17 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 18 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 19 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation2) >> >> endobj 20 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 21 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 22 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 23 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation2) >> >> endobj 24 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 25 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 26 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 27 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 28 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 29 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 30 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 31 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 32 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 33 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 34 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 35 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 36 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 37 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation113) >> >> endobj 40 0 obj << /D [11 0 R /XYZ 28.346 270.333 null] >> endobj 44 0 obj << /D [11 0 R /XYZ 334.488 0 null] >> endobj 45 0 obj << /D [11 0 R /XYZ 334.488 0 null] >> endobj 38 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F16 42 0 R /F18 43 0 R >> /XObject << /Fm1 12 0 R /Fm3 15 0 R /Fm4 16 0 R /Fm2 14 0 R >> /ProcSet [ /PDF /Text ] >> endobj 77 0 obj << /Length 1240 /Filter /FlateDecode >> stream xXKs6WV cn3iɡ큡iHƔ.lq6nNϞK+Z!Ï1A:pT󜀠 ) Ya'3:$'b(זYAɅ )s8uRFe,$e+4Qx7$pH"_x L#T0qZϙC0MS BgsԠIGp"EP>ϑШ2'P|w NP#c(F## laFs3OF137n70=J'v&jqQ Qτ? ko|ٌ3O?̈}~D^hwLY4#IPPjG.dh16i^"I%^)8FD1 ILVFɋHInFwB):;G_\~e)ˈ/]=2Q02OQ~cM+j]e:y_\kwyJ6LSv!h,?I::!AxGJ3Iƃ2EŧQ%.bP+zGIյ}=,^7@^vxÈڄYK w aqGD6s1Z3WXyt/ʽ2m0)nSW/Lr hqe Όs8ZK~\ g?.WΪMhۢ|ww2̻yXة n8ʩAM9v1.@O5_ź3Z!ӭ>vs-znL#J BG߽.53yY]~BݶQTB쯞um Dt^,(;+) 3sCIYHެ ]l]|} ˮnbfQy߷;5´ t6_u]zTk~_|,+ Wݾ^K*[j %vXos* p{9(n ;J0yp}#?G}0i c@]B6OhTWfW'KXֽm>m TDW% endstream endobj 76 0 obj << /Type /Page /Contents 77 0 R /Resources 75 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 46 0 R /Annots [ 54 0 R 55 0 R 56 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R 69 0 R 70 0 R 71 0 R 72 0 R 73 0 R 74 0 R ] >> endobj 53 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 362.835 272.126] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 81 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 81 0 obj << /Shading << /Sh << /ShadingType 2 /ColorSpace /DeviceRGB /Domain [0 1] /Coords [0.0 0 362.8394 0] /Function << /FunctionType 2 /Domain [0 1] /C0 [0.2 0.2 0.7] /C1 [0 0 0] /N 1 >> /Extend [false false] >> >> /ProcSet [ /PDF ] >> endobj 54 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 55 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 56 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation3) >> >> endobj 57 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 58 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation2) >> >> endobj 59 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation2) >> >> endobj 60 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation3) >> >> endobj 61 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 62 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 63 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 64 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 65 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 66 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 67 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 68 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 69 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 70 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 71 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 72 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 73 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 74 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation1) >> >> endobj 51 0 obj << /D [76 0 R /XYZ 334.488 0 null] >> endobj 80 0 obj << /D [76 0 R /XYZ 334.488 0 null] >> endobj 75 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm1 12 0 R /Fm5 53 0 R >> /ProcSet [ /PDF /Text ] >> endobj 105 0 obj << /Length 907 /Filter /FlateDecode >> stream xWKs9Wti|[GHjsZ6f8ń8׷[i&wYѧ~~i6p:Ãx$2`V8A+k| E T  䁒WGX^«n57 ClbH4t,AzpɋgtT ?9q, &BbyONLj| l, MT %ҤaAʛ-R}Fvs'oj,r&¢v`i2h 2i~[(/.f/2Oś,rUnݦ?bwfKpr6a+uï:Ho:tz[<^nkx'"z۠>W{Xqw1~ҟ;5 !glқoaHXeȤwE%*9i^ "L ƀf!B'f/Ebc9B9)({##Pe<Fd:QMTyvY&L8-eH B@ YQzHIةLQiEn\"@3WA$…dC o0*B|% )SC*Vs7=SF'~%VZhbƼxxǺ+~%JԨ#4M^n|P%I+ )ߋH[G5'g{5!VQ-yu73r]-єZ}yߢH xJΘ9}99wzِVo\qyñg݄SڪvxW[nzDAdGh7$JOjR4M$2Lf_G endstream endobj 104 0 obj << /Type /Page /Contents 105 0 R /Resources 103 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 46 0 R /Annots [ 83 0 R 84 0 R 85 0 R 86 0 R 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R 102 0 R ] >> endobj 83 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation2) >> >> endobj 84 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 85 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation4) >> >> endobj 86 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation2) >> >> endobj 87 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation3) >> >> endobj 88 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation3) >> >> endobj 89 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation4) >> >> endobj 90 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 91 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 92 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 93 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 94 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 95 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 96 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 97 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 98 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 99 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 100 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 101 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 102 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 82 0 obj << /D [104 0 R /XYZ 28.346 0 null] >> endobj 103 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 130 0 obj << /Length 723 /Filter /FlateDecode >> stream xWKS1 Wf”%N<)ii~e{eRrX>K^;瀰75I,F*:hE&*&;P%L3FҠQNtnm,b}j|&ӓf~uތUU|qtR[_g36WI2փ Ra"D[kI;'\)z$#ayk6%7m B&aCPLb&BvJ{GC Hl` h6"t09^Hfw8U?ǐM)[p&/@lr, #g@^G (F5Ǚ,ط"ΫLʵ&҂bdȲ$Gec"g͜⬷|}`."Z" L24Z>Deч -M q8Cf{ r|r">o.]bՏWd?p WOi%x'c7OryJE2/ROSd |$,{ImGڇXOUժ+wo&u<7~i endstream endobj 129 0 obj << /Type /Page /Contents 130 0 R /Resources 128 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 46 0 R /Annots [ 108 0 R 109 0 R 110 0 R 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R 116 0 R 117 0 R 118 0 R 119 0 R 120 0 R 121 0 R 122 0 R 123 0 R 124 0 R 125 0 R 126 0 R 127 0 R ] >> endobj 107 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/f4.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 131 0 R /BBox [125.5 369.95 403.708 525.659] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 134 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 135 0 R /Pat96 136 0 R >>>> /Length 657 /Filter /FlateDecode >> stream xڭnS1)f _;DvE44**=coQ4d?[ (>=SOJʉ HOr%|$|(1Bi{2(XW?f0vv3[LG녏Б4݊!-Ur8+4sp)ᶷO:8hiӜR3xAz) .G 2ԴFdOF\$\I-Y#K, Np(]ߥU/KwI(칲<J@0^zyxiN-ŧ NscbXKG? f`_yYeT o-uziI-ӳDZ]΀K{/q)php;>9R=&l>t&@^~0qn@gD+GG0&v endstream endobj 131 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130211121428) >> endobj 134 0 obj << /Type /Font /Subtype /Type1 /FirstChar 97 /LastChar 121 /Widths [ 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7 461.1 683.3 461.1 461.1] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 133 0 R >> endobj 135 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 136 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 133 0 obj << /Type /Encoding /Differences [97/a 99/c/d/e 105/i 108/l/m/n/o/p 114/r 116/t/u 119/w/x/y] >> endobj 108 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation3) >> >> endobj 109 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 110 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation5) >> >> endobj 111 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation3) >> >> endobj 112 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation4) >> >> endobj 113 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation4) >> >> endobj 114 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation5) >> >> endobj 115 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 116 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 117 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 118 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 119 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 120 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 121 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 122 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 123 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 124 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 125 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 126 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 127 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 106 0 obj << /D [129 0 R /XYZ 28.346 0 null] >> endobj 128 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im7 107 0 R >> /ProcSet [ /PDF /Text ] >> endobj 162 0 obj << /Length 831 /Filter /FlateDecode >> stream xWKo1W1Zwo T 8JM{3&]ZJEi/y曧 pk$ǯ U4tЊ#8tb"`q 2ނB7SXr}ODNCd>7is[l\ClnmpTMUB~,d9L>mΙ^kzM]ָȫBd-F?Re)9vTlȺ^R+8X.?"{~?sz_ {M8Kv_/x]'{/nzKl|YRKSXğ- y BmHT/GUhH2M~թ endstream endobj 161 0 obj << /Type /Page /Contents 162 0 R /Resources 160 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 46 0 R /Annots [ 140 0 R 141 0 R 142 0 R 143 0 R 144 0 R 145 0 R 146 0 R 147 0 R 148 0 R 149 0 R 150 0 R 151 0 R 152 0 R 153 0 R 154 0 R 155 0 R 156 0 R 157 0 R 158 0 R 159 0 R ] >> endobj 139 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/ex1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 166 0 R /BBox [192 445.469 414.148 527.462] /Resources << /ProcSet [ /PDF /Text ] /Font << /F7 169 0 R /F8 172 0 R /F11 175 0 R /F14 178 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 179 0 R /Pat96 180 0 R >>>> /Length 536 /Filter /FlateDecode >> stream xUMo0Wq K%[!V=Lv7d˥{c ԷǁY >o]_5>]=`a^q2> d̑"Tģd ]Au,A OI1'/5"` A<8(bvgmb|͠0^h(L  0[!/I"o[M(|VbtV:whV6cYWpFUӌ(&TrˍJi Ȫn鶫iNa9i92ܸ?[JTڔu" K"VDa9yQȬ?l8UΓ("H&E%{ۚ|D;,UΎ~שE),| >21t|qʾ4gS~M3 `ݹ#er|4d94:N>j=O v(gtKrqKFl#9JM&C,-^u:,BNV?h@ endstream endobj 166 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130206150356) /ModDate (D:20130206171534) >> endobj 169 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 168 0 R >> endobj 172 0 obj << /Type /Font /Subtype /Type1 /FirstChar 40 /LastChar 61 /Widths [ 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 171 0 R >> endobj 175 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 174 0 R >> endobj 178 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 177 0 R >> endobj 179 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 180 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 177 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 174 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 171 0 obj << /Type /Encoding /Differences [40/parenleft/parenright 43/plus 49/one/two 52/four 61/equal] >> endobj 168 0 obj << /Type /Encoding /Differences [50/two] >> endobj 140 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation4) >> >> endobj 141 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 142 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation6) >> >> endobj 143 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation4) >> >> endobj 144 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation5) >> >> endobj 145 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation5) >> >> endobj 146 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation6) >> >> endobj 147 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 148 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 149 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 150 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 151 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 152 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 153 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 154 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 155 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 156 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 157 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 158 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 159 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 138 0 obj << /D [161 0 R /XYZ 28.346 0 null] >> endobj 160 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im8 139 0 R >> /ProcSet [ /PDF /Text ] >> endobj 209 0 obj << /Length 858 /Filter /FlateDecode >> stream xWnT1 Wx M ؔXTSb(Es;NL/RLn>v,xo$L.Z\ ;X#6Kz8`tjq$6Dc]"kazAO$]|Ԕ$:ŏk6R-dV>OJt$O4| 7 P>̀Br 31!,v>QJ?ُH> /Parent 46 0 R /Annots [ 187 0 R 188 0 R 189 0 R 190 0 R 191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R 203 0 R 204 0 R 205 0 R 206 0 R ] >> endobj 186 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/ex3.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 210 0 R /BBox [144 282.36 274.077 342.289] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 213 0 R /F7 215 0 R /F8 217 0 R /F11 219 0 R /F14 221 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 222 0 R /Pat96 223 0 R >>>> /Length 609 /Filter /FlateDecode >> stream xڽVMo0 Wb'(]lz[ӊC{YG[Q`(4Ǐ';{m2tC'ux_g+s4 $5rѮdvdwfs/oZ+5Hm@{#c_5MP!zb*;q4 #ߝs9p;جRQ$u84ŘIˉC,q8⨊.un8d^iwJ"ym3!JqͭQ7d$.oƔBƁjP[Xt>S5U%SpX" Aw,s 6^$)ҒiIG8iTBiD (S})uvMY( .AGW!bhQ"!jwc,A.q/|z?Q9 _H[c&"֝xI\|IjŅMu:t6ssH>ua1wmz:?jAN!dfA{znK%- å3s!IҔBb.LZ#|.˻R% 5% endstream endobj 210 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130206152453) /ModDate (D:20130206171312) >> endobj 213 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 212 0 R >> endobj 215 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 214 0 R >> endobj 217 0 obj << /Type /Font /Subtype /Type1 /FirstChar 43 /LastChar 50 /Widths [ 777.8 277.8 333.3 277.8 500 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 216 0 R >> endobj 219 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 218 0 R >> endobj 221 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 220 0 R >> endobj 222 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 223 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 220 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 218 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 216 0 obj << /Type /Encoding /Differences [43/plus 48/zero/one/two] >> endobj 214 0 obj << /Type /Encoding /Differences [50/two] >> endobj 212 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 187 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation5) >> >> endobj 188 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 189 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation7) >> >> endobj 190 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation5) >> >> endobj 191 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation6) >> >> endobj 192 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation6) >> >> endobj 193 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation7) >> >> endobj 194 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 195 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 196 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 197 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 198 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 199 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 200 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 201 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 202 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 203 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 204 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 205 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 206 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 185 0 obj << /D [208 0 R /XYZ 28.346 0 null] >> endobj 207 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im8 139 0 R /Im9 186 0 R >> /ProcSet [ /PDF /Text ] >> endobj 249 0 obj << /Length 781 /Filter /FlateDecode >> stream xW=s1+L't $Cw@uP`'Ww/ !CHKz}tIL' ` ֤Γֈ t.g{Jw_GǒI\ 1!; GGzw`?NJFöM9HHlrU :KX[4Oi !r" Skcq{Xy~1u)`7a[[;6ܒ ^J%;Z.4 B"jqz(q3ƦH4h"O LuKՖE!HKqٖ7kaz vCTpKAޞ4+芵`JhZ) +.'O?$cC]8Bf]GB¾sZhήm!p|ΠcĞs5 bT3c z*"E*ݞUU:q;%- Q"<Ss%u٬pȹh^+|͕9HF52BPQa{ 9ƀUexś̷*S86(tn{FUIe,G6U#(pc(YO9$Kzd[C?34MȆxqrV39u%g!k ]EbBtF^1j ] EJJO9}J+{q \7Uqpwr)o[toˋ7z;\1).ڕXiXԟ+2Eڇq~yKTvUi iHd8, 4 endstream endobj 248 0 obj << /Type /Page /Contents 249 0 R /Resources 247 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 250 0 R /Annots [ 227 0 R 228 0 R 229 0 R 230 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R 236 0 R 237 0 R 238 0 R 239 0 R 240 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R ] >> endobj 226 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/ex2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 251 0 R /BBox [117.797 284.492 517.541 367.462] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 253 0 R /F7 255 0 R /F8 257 0 R /F11 259 0 R /F14 261 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 262 0 R /Pat96 263 0 R >>>> /Length 860 /Filter /FlateDecode >> stream xXKO0WxƯC/H-7ڽm9*z)~N6! +ű'73߮Qgԏ&nc모N{Uc'ǨNzYǤ֗_DZ2S"HP^1K8(֞|"i]䵏V-/ƘAyŵλJĨia]#<:00Eh`vtB-7*pت낣gH@NCJ43A|OxNN$m01;lK&EV"#YܚBup Cɉc!n~6+:z0Tld+"ިpߪiYSUiֶqGa w㐂Q^<"/;%(r ovr^s)mǛH{ -\!~;!ђ rNfEd `|B> endobj 253 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 252 0 R >> endobj 255 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 254 0 R >> endobj 257 0 obj << /Type /Font /Subtype /Type1 /FirstChar 40 /LastChar 61 /Widths [ 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 256 0 R >> endobj 259 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 258 0 R >> endobj 261 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 260 0 R >> endobj 262 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 263 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 260 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 258 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 256 0 obj << /Type /Encoding /Differences [40/parenleft/parenright 43/plus 48/zero/one/two 61/equal] >> endobj 254 0 obj << /Type /Encoding /Differences [50/two] >> endobj 252 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 227 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation6) >> >> endobj 228 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 229 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation8) >> >> endobj 230 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation6) >> >> endobj 231 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation7) >> >> endobj 232 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation7) >> >> endobj 233 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation8) >> >> endobj 234 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 235 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 236 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 237 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 238 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 239 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 240 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 241 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 242 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 243 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 244 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 245 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 246 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 225 0 obj << /D [248 0 R /XYZ 28.346 0 null] >> endobj 247 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im10 226 0 R >> /ProcSet [ /PDF /Text ] >> endobj 288 0 obj << /Length 785 /Filter /FlateDecode >> stream xW;s1+LI1 BABaH|yugHBX>0%1,xg;$L.Z\ Y#6'Xu|ZK&hiuA"bbd%EZ}w8fg:TD&G0 m0Ęh9Q{sOsq=QF..R-mg[ެE74 fP.iGyAotHB@=A蚊 3VAP9GJ¡sZiή$frq7oYUNJڄ \aWA'~ S2xXTk珠wÍud=xʓ,}z[o =g4KxqsQV38"Kb"8=^:ޅ&W"\M"x)U: 4 JO9}J+ {!۷VoDV%ㅻ;<Kvv.xk]^vޯKu*կt565iJXǐĕ4 cM.QiTMK!/aO endstream endobj 287 0 obj << /Type /Page /Contents 288 0 R /Resources 286 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 250 0 R /Annots [ 266 0 R 267 0 R 268 0 R 269 0 R 270 0 R 271 0 R 272 0 R 273 0 R 274 0 R 275 0 R 276 0 R 277 0 R 278 0 R 279 0 R 280 0 R 281 0 R 282 0 R 283 0 R 284 0 R 285 0 R ] >> endobj 265 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/ex4.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 289 0 R /BBox [117.797 284.492 517.541 366.825] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 291 0 R /F7 293 0 R /F8 295 0 R /F11 297 0 R /F14 299 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 300 0 R /Pat96 301 0 R >>>> /Length 853 /Filter /FlateDecode >> stream xXMO0Wvx1>T z**UUp)$%&ۂVZ9qo°QKV.D#ΚJ7gh@nҔ0r$h8QOÀŏ Cr2N=׻cmyzPR:]V'gl2Y~jLފYTWGY^`vCAB;׳2,&#I7։3b ^fmy}=Bi\[ke#3>wJ/Zh6GvRn\>ܮΫY&nl\Y(-4'O#OdA_s[<#3)}$`|7P(ZR!ij?ܮHXS#L>D|KۥX쏠%|e\WldROcJ=ll؀\"e6"X<}eSQcp$Z$"] .bw}l}''&q i>PJ|ki3rf[6F8¶gO($ 8FIh=Zs΀m!Ea$MfFOeehMF@rF@P5 i=r!̎"wqZxgvٍ_.Jn4ܶ׶`W{^/^Ëq^pGE{Y-|D[z vTU(={{Xti@ . F]VZewipuҥq#, 4Ҩ,M"Sp+w6R5'O#f'^ W^_?tqbȎzm6{kFP@7r endstream endobj 289 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130206152453) /ModDate (D:20130206171717) >> endobj 291 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 290 0 R >> endobj 293 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 292 0 R >> endobj 295 0 obj << /Type /Font /Subtype /Type1 /FirstChar 40 /LastChar 61 /Widths [ 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 294 0 R >> endobj 297 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 296 0 R >> endobj 299 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 298 0 R >> endobj 300 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 301 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 298 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 296 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 294 0 obj << /Type /Encoding /Differences [40/parenleft/parenright 43/plus 48/zero/one/two 61/equal] >> endobj 292 0 obj << /Type /Encoding /Differences [50/two] >> endobj 290 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 266 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation7) >> >> endobj 267 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 268 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation9) >> >> endobj 269 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation7) >> >> endobj 270 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation8) >> >> endobj 271 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation8) >> >> endobj 272 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation9) >> >> endobj 273 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 274 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 275 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 276 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 277 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 278 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 279 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 280 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 281 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 282 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 283 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 284 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 285 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 264 0 obj << /D [287 0 R /XYZ 28.346 0 null] >> endobj 286 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im11 265 0 R >> /ProcSet [ /PDF /Text ] >> endobj 326 0 obj << /Length 785 /Filter /FlateDecode >> stream xW;s1+LI1 BABaH|yugHBX>0%1,xg;$L.Z\ Y#6'Xu|ZK&hiuA"bbd%EZ}w8fg:TD&G0 m0Ęh9Q{sOsq=QF..R-mg[ެҫoh͠ _]ҎI"ك+ޢ鐄{4 )5D3g4 s,C#8+V]mI@xޠcĞs5Ķ 3vH|PSj_'.ܹ\b繤u&bcģ=:G3SN˔lf\K4hU~͕9!d=@G}*&5N/o2߲ǝ1 Eץv3N(̧(e:"\AIGzZ%'Y&zhЍE9梬"g$pE ֗Ep>z>t# M Eй:D"g/ WS >t7*i4b/>71sd=V  ',S!xEcCoz$JB wwayzK+"]O x_T_j> /Parent 250 0 R /Annots [ 304 0 R 305 0 R 306 0 R 307 0 R 308 0 R 309 0 R 310 0 R 311 0 R 312 0 R 313 0 R 314 0 R 315 0 R 316 0 R 317 0 R 318 0 R 319 0 R 320 0 R 321 0 R 322 0 R 323 0 R ] >> endobj 303 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/ex5.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 327 0 R /BBox [117.797 284.492 517.541 366.825] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 329 0 R /F7 331 0 R /F8 333 0 R /F11 335 0 R /F14 337 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 338 0 R /Pat96 339 0 R >>>> /Length 884 /Filter /FlateDecode >> stream xXn1W]>pHr""CrI/vOg! FJv^XRuX[.}k>@2X*%fEhNhX:obէRǬ@wJ"XlͫƨD)ؠ֟!WcRZCFT$`06R2@!Z>jw}yİzX{ X/H\#pPұ#`N8lJa 06- ؾϒBܚP;Ȫ͞l /E;6W"9Ff@*Id\ I嘤=-!di6pe Yؒ$MCP5E8J# #e 7ՖqB(H@6WyMNJ#.+1 4,`E,][|fxphQ<96g? 6%/\/llj40o@JqBbHoh,8:GFdkqÜA\sbK)ԥ~6QrǕ{e[#Ywr88 |Ҍj_=}r~@f5wx׿pi0p*@1,-тMR؝-2=]}Ӵ0b;0a~Z &/φe0(OږL'ڦIsmٞr+ash[nLE&gh*gSq?6bAWfGezOvͪsM{BM >\2R3Zg gSrá ~:ng endstream endobj 327 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130206152453) /ModDate (D:20130206171740) >> endobj 329 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 328 0 R >> endobj 331 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 330 0 R >> endobj 333 0 obj << /Type /Font /Subtype /Type1 /FirstChar 40 /LastChar 61 /Widths [ 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 332 0 R >> endobj 335 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 334 0 R >> endobj 337 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 336 0 R >> endobj 338 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 339 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 336 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 334 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 332 0 obj << /Type /Encoding /Differences [40/parenleft/parenright 43/plus 48/zero/one/two 52/four 61/equal] >> endobj 330 0 obj << /Type /Encoding /Differences [50/two] >> endobj 328 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 304 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation8) >> >> endobj 305 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 306 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation10) >> >> endobj 307 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation8) >> >> endobj 308 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation9) >> >> endobj 309 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation9) >> >> endobj 310 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation10) >> >> endobj 311 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 312 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 313 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 314 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 315 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 316 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 317 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 318 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 319 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 320 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 321 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 322 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 323 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 302 0 obj << /D [325 0 R /XYZ 28.346 0 null] >> endobj 324 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im12 303 0 R >> /ProcSet [ /PDF /Text ] >> endobj 363 0 obj << /Length 705 /Filter /FlateDecode >> stream xWKo1ﯘcr;OH$CYh{ }{F-9w>{ \q{#Hb%!kJVo`a B-}8!k&Qi|lH 21]l-dn  )1ek]o :F9 #KlXp~Wvi_U &iAEN12dy$GԐ%zAЧ,Q0 3\/"EDk\EV!D }Ehz)9NTb,i[pU =HE(;}ސ]W#{M8=ŗx}=u̵;t;/H%.ROZ I>Z$ Y!CS}y&EB@͛ɰY_v; endstream endobj 362 0 obj << /Type /Page /Contents 363 0 R /Resources 361 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 250 0 R /Annots [ 341 0 R 342 0 R 343 0 R 344 0 R 345 0 R 346 0 R 347 0 R 348 0 R 349 0 R 350 0 R 351 0 R 352 0 R 353 0 R 354 0 R 355 0 R 356 0 R 357 0 R 358 0 R 359 0 R 360 0 R ] >> endobj 341 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation9) >> >> endobj 342 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 343 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation11) >> >> endobj 344 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation9) >> >> endobj 345 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation10) >> >> endobj 346 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation10) >> >> endobj 347 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation11) >> >> endobj 348 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 349 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 350 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 351 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 352 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 353 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 354 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 355 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 356 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 357 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 358 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 359 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 360 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 340 0 obj << /D [362 0 R /XYZ 28.346 0 null] >> endobj 361 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im7 107 0 R >> /ProcSet [ /PDF /Text ] >> endobj 387 0 obj << /Length 896 /Filter /FlateDecode >> stream xWM5 ϯqq$TQ@ e8V1;ŰT¿Gv!˸,=IOvl$IAM8!pӻlWO&c&ހM&duׯ.66áq=x89͈59ɎHڞ8E '66LY)xX$A~R-!?=m,,a0S G@*+(."X#Ʀh-HЗ.Wr0d7fwHvCrTno6x `jT9qW˦P &GK$Z4IRL9IQq}-K-S,4}E^SV *ƣCG}:r/KV8)TUӖR|_v֫z{e9Kv'w6Gn)}-}_>[C_ 4O U.51YHYshYPk!$7Qc){ITc|hY(TG DgXi7޳]"Uױ_ 練r)ϭ/EFogn7WBRSq)zڤkӼ5a%%Q,i/q\yU͊慤Q/oߚ endstream endobj 386 0 obj << /Type /Page /Contents 387 0 R /Resources 385 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 250 0 R /Annots [ 365 0 R 366 0 R 367 0 R 368 0 R 369 0 R 370 0 R 371 0 R 372 0 R 373 0 R 374 0 R 375 0 R 376 0 R 377 0 R 378 0 R 379 0 R 380 0 R 381 0 R 382 0 R 383 0 R 384 0 R ] >> endobj 365 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation10) >> >> endobj 366 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 367 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation12) >> >> endobj 368 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation10) >> >> endobj 369 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation11) >> >> endobj 370 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation11) >> >> endobj 371 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation12) >> >> endobj 372 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 373 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 374 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 375 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 376 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 377 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 378 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 379 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 380 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 381 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 382 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 383 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 384 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 364 0 obj << /D [386 0 R /XYZ 28.346 0 null] >> endobj 385 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im8 139 0 R /Im9 186 0 R >> /ProcSet [ /PDF /Text ] >> endobj 412 0 obj << /Length 885 /Filter /FlateDecode >> stream xWM[E Wxe=;}eWX@)Iϙ3&iK[̌}l{>1nl%$L.Z] Wzyra㷇#)$8-X,a1~#3_s8M?dz]Tަ p0N`)=֙UX2\PUkDcץ&|ԬZ&.LΙdtb}lEi&t_NnYSkK3 ݒX 9SBhPzpxa#sXo<':p4t4g{ks'q_iok;ܸ[Kv9ĽE%m. (D@dccc¤5Z9'ȋpmTinѭ$xހq1x+% HUb: }vD4b{;s6M&.7]5Ғ1C1 Q5k"8K2pq+Ѥ}R ƕk"d>A 0PRX_AT<3YUMH%ϩ(vn=*"G`DˁG3(;ƺ'%/Jm5x@n7.±Te9< @HG7"wKUV'.a/WS T}أPIS!.R9ҋ3һۏiZ`8Kg_l>ת5Ihp#l /oiR}o®/;n[Rb[J+Yi> /Parent 250 0 R /Annots [ 390 0 R 391 0 R 392 0 R 393 0 R 394 0 R 395 0 R 396 0 R 397 0 R 398 0 R 399 0 R 400 0 R 401 0 R 402 0 R 403 0 R 404 0 R 405 0 R 406 0 R 407 0 R 408 0 R 409 0 R ] >> endobj 389 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/c0.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 413 0 R /BBox [240 422.33 322.686 457.659] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 415 0 R /F7 417 0 R /F8 419 0 R /F11 421 0 R /F14 423 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 424 0 R /Pat96 425 0 R >>>> /Length 356 /Filter /FlateDecode >> stream xڭRN1 ac'qV$ԭ6`Q ѡ,#rmaA'Eı? xu[[}A> endobj 415 0 obj << /Type /Font /Subtype /Type1 /FirstChar 20 /LastChar 21 /Widths [ 527.8 527.8] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 414 0 R >> endobj 417 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 416 0 R >> endobj 419 0 obj << /Type /Font /Subtype /Type1 /FirstChar 49 /LastChar 50 /Widths [ 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 418 0 R >> endobj 421 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 420 0 R >> endobj 423 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 422 0 R >> endobj 424 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 425 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 422 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 420 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 418 0 obj << /Type /Encoding /Differences [49/one/two] >> endobj 416 0 obj << /Type /Encoding /Differences [50/two] >> endobj 414 0 obj << /Type /Encoding /Differences [20/bracketleftbigg/bracketrightbigg] >> endobj 390 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation11) >> >> endobj 391 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 392 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation13) >> >> endobj 393 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation11) >> >> endobj 394 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation12) >> >> endobj 395 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation12) >> >> endobj 396 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation13) >> >> endobj 397 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 398 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 399 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 400 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 401 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 402 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 403 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 404 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 405 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 406 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 407 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 408 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 409 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 388 0 obj << /D [411 0 R /XYZ 28.346 0 null] >> endobj 410 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R /F39 78 0 R /F21 79 0 R >> /XObject << /Im13 389 0 R >> /ProcSet [ /PDF /Text ] >> endobj 450 0 obj << /Length 929 /Filter /FlateDecode >> stream xWM6 ϯ1A1Z"͢)ٹ=9hE(>ɦd{o$M.#&Hِ>feHȸ(6`dݭyqxrag:Ŝ^f1{#hNͳ{rG/5KS548lsDUabZI6d h=nwVeH x"kؘln{XxƹHWobVWQ@5{n㡐&sW<6 UIkpL[Za{vKv"~_떫_|>mӝ5Ӭ5`x(]MNJ/)/鰼/"5 endstream endobj 449 0 obj << /Type /Page /Contents 450 0 R /Resources 448 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 451 0 R /Annots [ 428 0 R 429 0 R 430 0 R 431 0 R 432 0 R 433 0 R 434 0 R 435 0 R 436 0 R 437 0 R 438 0 R 439 0 R 440 0 R 441 0 R 442 0 R 443 0 R 444 0 R 445 0 R 446 0 R 447 0 R ] >> endobj 427 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/c1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 452 0 R /BBox [240 422.17 489.199 467.271] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 454 0 R /F7 456 0 R /F8 458 0 R /F11 460 0 R /F14 462 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 463 0 R /Pat96 464 0 R >>>> /Length 617 /Filter /FlateDecode >> stream xVM1 W $u] VKoeO(Bн73|U8<٥Ye&qY'>gѼH1Q,~m޼P\Sl>8WOv4of !۔ e Uؽ4dT;#8J^fe/C xG,=q n0L P*X<$\`xRu#Tobّg  h5(J& Ѫ *C> 8&qX,˱p55mF*IrPvBчY^)$%rZ R9*A-dѧbGYG-m[f.•lzf}&M'""i͠+Ni E1 jp\ņj>@ҤXk}%Aࡊ@U?:pi#R"dct+8*W(MͅĕX1 v~3?Wm endstream endobj 452 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130206170901) >> endobj 454 0 obj << /Type /Font /Subtype /Type1 /FirstChar 20 /LastChar 21 /Widths [ 527.8 527.8] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 453 0 R >> endobj 456 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 455 0 R >> endobj 458 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 50 /Widths [ 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 457 0 R >> endobj 460 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 459 0 R >> endobj 462 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 461 0 R >> endobj 463 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 464 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 461 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 459 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 457 0 obj << /Type /Encoding /Differences [48/zero/one/two] >> endobj 455 0 obj << /Type /Encoding /Differences [50/two] >> endobj 453 0 obj << /Type /Encoding /Differences [20/bracketleftbigg/bracketrightbigg] >> endobj 428 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation12) >> >> endobj 429 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 430 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation14) >> >> endobj 431 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation12) >> >> endobj 432 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation13) >> >> endobj 433 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation13) >> >> endobj 434 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation14) >> >> endobj 435 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 436 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 437 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 438 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 439 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 440 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 441 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 442 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 443 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 444 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 445 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 446 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 447 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 426 0 obj << /D [449 0 R /XYZ 28.346 0 null] >> endobj 448 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R /F39 78 0 R /F21 79 0 R >> /XObject << /Im14 427 0 R >> /ProcSet [ /PDF /Text ] >> endobj 489 0 obj << /Length 867 /Filter /FlateDecode >> stream xWMo1 4$pC 8[4mAQKf-f~ޒ#c &֓b.;F.Z]3&97ލ5;L>hpR@Es2:L`DBHz)l˒-NʃV&|b͞}¶fc)'Ɯ-Qɩ.XZ2wE.1bǀfP!)zF$*JU:̈́d>8V.M$xNʥ"%Ht+-$(yPe!Y#CQݜEVe3q¦]%S!FFXFCvd3'<ٜ73gh^@ +ڌFqDPQas I]0K%&5"Sب _nХZ_m~ cy`2+3fUxL$ɘLrΟ endstream endobj 488 0 obj << /Type /Page /Contents 489 0 R /Resources 487 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 451 0 R /Annots [ 467 0 R 468 0 R 469 0 R 470 0 R 471 0 R 472 0 R 473 0 R 474 0 R 475 0 R 476 0 R 477 0 R 478 0 R 479 0 R 480 0 R 481 0 R 482 0 R 483 0 R 484 0 R 485 0 R 486 0 R ] >> endobj 466 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/c2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 490 0 R /BBox [209.516 421.284 517.257 469.83] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 492 0 R /F7 494 0 R /F8 496 0 R /F11 498 0 R /F14 500 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 501 0 R /Pat96 502 0 R >>>> /Length 786 /Filter /FlateDecode >> stream xVKo@WyZV%A vxcFD(B(RƙCklU!ƏM6k6'o>Nes PT' FWa% k/]s~v~lagT:WHp}Q" ᄳ gȰS[pSu;^mȄr\\6f1UfܿX>MsqY 6FTh,#WTdYMs<̢8I__7C޲O&ƌ!+9E RۦS?6c)@c\ʌӇU'iYb*29B%2FB.E*u?El^Ո '\(Ĩf ɮ\gwUH+| ~sa;u<\i(d Fl@QW{r @5eT#9T2ɀ^a4:Oz9f8$cx!<(a h9l`1΋s#akYCFըmjm_ #Kf4"_)KG[oqo3X[Ξ{2nl(bgLq▌69R.,_rT)ynse bt㠧ΧYj/g{p"@ӿ3hRK[O-3vSb6v$>Bӻ({<'!;L endstream endobj 490 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130206170919) >> endobj 492 0 obj << /Type /Font /Subtype /Type1 /FirstChar 20 /LastChar 53 /Widths [ 527.8 527.8 583.3 583.3 583.3 583.3 750 750 750 750 1044.4 1044.4 791.7 791.7 583.3 583.3 638.9 638.9 638.9 638.9 805.6 805.6 805.6 805.6 1277.8 1277.8 811.1 811.1 875 875 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 491 0 R >> endobj 494 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 493 0 R >> endobj 496 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 50 /Widths [ 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 495 0 R >> endobj 498 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 497 0 R >> endobj 500 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 499 0 R >> endobj 501 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 502 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 499 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 497 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 495 0 obj << /Type /Encoding /Differences [48/zero/one/two] >> endobj 493 0 obj << /Type /Encoding /Differences [50/two] >> endobj 491 0 obj << /Type /Encoding /Differences [20/bracketleftbigg/bracketrightbigg 50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt] >> endobj 467 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation13) >> >> endobj 468 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 469 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation15) >> >> endobj 470 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation13) >> >> endobj 471 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation14) >> >> endobj 472 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation14) >> >> endobj 473 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation15) >> >> endobj 474 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 475 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 476 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 477 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 478 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 479 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 480 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 481 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 482 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 483 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 484 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 485 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 486 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 465 0 obj << /D [488 0 R /XYZ 28.346 0 null] >> endobj 487 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R /F39 78 0 R >> /XObject << /Im15 466 0 R >> /ProcSet [ /PDF /Text ] >> endobj 527 0 obj << /Length 868 /Filter /FlateDecode >> stream xWMo1W1뱽VS m D=ތRQKy3o>֎wp7VX@zxm'b󆖗'Grs:ˣ΍5h4SR#¢N&0D}HzQ<\{܈YT-LvYN LccR9 8[rlW,^wW'f܀[8ˤ5]'MN!)laꂛzcETĆMGʼn ί.1A̐B[b̙ݐV/ `6+1lˀvBdS;eGf6Т1.)͎Ut&<еʥ"%ItX-$6fAPƆCl7SѬDۿNW)ؔ]IC #<& lv4ou6sK$/nFqDPQas Bإ_BTzU=6*qMEWt3W@G|A%o^./O@IokGz\q%GYһ&y@TIj"ө\ظ3=I9p}\DlW%rًJ3㊀)uT|ȾQ)[Tzz_qSdڌuJG.符2!灬RJHwsa,A؜O޵;L;vs%̧n*x,$CS16> /Parent 451 0 R /Annots [ 505 0 R 506 0 R 507 0 R 508 0 R 509 0 R 510 0 R 511 0 R 512 0 R 513 0 R 514 0 R 515 0 R 516 0 R 517 0 R 518 0 R 519 0 R 520 0 R 521 0 R 522 0 R 523 0 R 524 0 R ] >> endobj 504 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/c3.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 528 0 R /BBox [187.817 419.666 516.208 479.596] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 530 0 R /F7 532 0 R /F8 534 0 R /F11 536 0 R /F14 538 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 539 0 R /Pat96 540 0 R >>>> /Length 881 /Filter /FlateDecode >> stream xXKo1z<}DV8B^޼MVТHf<|q!5Ίёq\ê–s6u)= Y6߻zkmwE Iz[_~v0V{guÉlJ6]l֠{ @{+j2MFśO7ۥ_Agv;"`#+VewvA&۬^ Tc&+Λ,Ah3G]z6,)4#(6`9omQ8zAy&cL fds%w&9 ,m* "* $T_3_+GWoyR]n~@o"Iq 2+eb{dRZ&*re NEḲ0hь 0:YƹY~ FDsTTW [0'Q=:\ !I>)RfW潄1P6`+}.[U3.qx=KJÁ i-5D:HjD"旖(-V;ʬ&L=-O4n BʉZJR- > 1$$AaҩU'wFZu<δC#$'T&*斪L2r !BΡGD#}Fho MQwk"~?=}3G"tHX?N6MͣZ=q ]Jҧ~ki"J  yG)q;Qp{ȝ@?r7}<0,,+u P daA?v~|n ~ip]{sjTMn":3 endstream endobj 528 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130206171052) >> endobj 530 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 529 0 R >> endobj 532 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 531 0 R >> endobj 534 0 obj << /Type /Font /Subtype /Type1 /FirstChar 43 /LastChar 50 /Widths [ 777.8 277.8 333.3 277.8 500 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 533 0 R >> endobj 536 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 535 0 R >> endobj 538 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 537 0 R >> endobj 539 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 540 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 537 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 535 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 533 0 obj << /Type /Encoding /Differences [43/plus 48/zero/one/two] >> endobj 531 0 obj << /Type /Encoding /Differences [50/two] >> endobj 529 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 505 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation14) >> >> endobj 506 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 507 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation16) >> >> endobj 508 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation14) >> >> endobj 509 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation15) >> >> endobj 510 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation15) >> >> endobj 511 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation16) >> >> endobj 512 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 513 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 514 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 515 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 516 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 517 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 518 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 519 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 520 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 521 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 522 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 523 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 524 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 503 0 obj << /D [526 0 R /XYZ 28.346 0 null] >> endobj 525 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R /F39 78 0 R >> /XObject << /Im16 504 0 R >> /ProcSet [ /PDF /Text ] >> endobj 565 0 obj << /Length 864 /Filter /FlateDecode >> stream xWKo1W1;c{68h ٛnR*J{of?tFL` DאmhyB7Wn;>Ov$x|4?%1!yVLkt4;{kLkHdR@Ec9f Mf#̼a̺ˌ=atl} kUWr>e`d|n6 ڲ>,Kj5L;Kk"W i%Z7ZH3ڐݯ^$y8q֤J 4b@[P!r)6I46|e!Vlpw!Mdi}V[ sby."{T*A꤫Rp5w5 0J*W!C}@j G),S!xcCozW%ȬH26V,E]m v~F{.%x~|dpVEOր|H /[KAS16OؤgUdHX^F endstream endobj 564 0 obj << /Type /Page /Contents 565 0 R /Resources 563 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 451 0 R /Annots [ 543 0 R 544 0 R 545 0 R 546 0 R 547 0 R 548 0 R 549 0 R 550 0 R 551 0 R 552 0 R 553 0 R 554 0 R 555 0 R 556 0 R 557 0 R 558 0 R 559 0 R 560 0 R 561 0 R 562 0 R ] >> endobj 542 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/c4.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 566 0 R /BBox [186.768 417.845 516.208 486.843] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 568 0 R /F7 570 0 R /F8 572 0 R /F11 574 0 R /F14 576 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 577 0 R /Pat96 578 0 R >>>> /Length 831 /Filter /FlateDecode >> stream xXMO1TAs*ϻZ,@"Exߌ=)֜6ߛ;cICsyE㢐l$EŒZ6?OzgmgeK%[\9y\M;k; Ĕז-U!kհ]liFYBRjD z4P Ñpuf_k`]h/2hoj dH4^w>C*f]!$  !CjE('b(.Xrs~em r{=npx&]ն˿!F0 Kǒ~KttNߪtt8;Ws ωH{ endstream endobj 566 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212155811) >> endobj 568 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 567 0 R >> endobj 570 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 569 0 R >> endobj 572 0 obj << /Type /Font /Subtype /Type1 /FirstChar 43 /LastChar 50 /Widths [ 777.8 277.8 333.3 277.8 500 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 571 0 R >> endobj 574 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 573 0 R >> endobj 576 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 575 0 R >> endobj 577 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 578 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 575 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 573 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 571 0 obj << /Type /Encoding /Differences [43/plus 48/zero/one/two] >> endobj 569 0 obj << /Type /Encoding /Differences [50/two] >> endobj 567 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 543 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation15) >> >> endobj 544 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 545 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation17) >> >> endobj 546 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation15) >> >> endobj 547 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation16) >> >> endobj 548 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation16) >> >> endobj 549 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation17) >> >> endobj 550 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 551 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 552 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 553 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 554 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 555 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 556 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 557 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 558 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 559 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 560 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 561 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 562 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 541 0 obj << /D [564 0 R /XYZ 28.346 0 null] >> endobj 563 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im17 542 0 R >> /ProcSet [ /PDF /Text ] >> endobj 604 0 obj << /Length 1077 /Filter /FlateDecode >> stream xXMs5qi)pp2puTP&'J\,?^KZKJH|%g#cdo!B;EA["VNvzuqb윣`C8%ׂ&iP(xkuܚVӓT0YA< (aII71 ]7u-Oˎi /*ϖAB3,)8w&(Icn1fsZׇ׷˫a.Mf!mB!OD"H8zF A* AO"+ ,~ z'ZЁ4oE $E3͟Qj֙H1g?9ޠ+.";M1Tsb)5 +q 47̀vhBfF"9ЈLZCAx? vo 7[V$*C݄YG]ai艭H?  NцK%CVV%"ḧ4q 4OZ-fNzHe^{O[zu83OΎ z+V'b""q93'4Ql%q^E pf&x˭Q%txAࢊŤ\DOZیI9s) UR^&}0~GHWSpQ}H$^T1Kd{,Ȓ Y)r8K*L?96.Xa}U_6^E~I[KŸYuq!O4c~&TU60$c2C֨ endstream endobj 603 0 obj << /Type /Page /Contents 604 0 R /Resources 602 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 451 0 R /Annots [ 582 0 R 583 0 R 584 0 R 585 0 R 586 0 R 587 0 R 588 0 R 589 0 R 590 0 R 591 0 R 592 0 R 593 0 R 594 0 R 595 0 R 596 0 R 597 0 R 598 0 R 599 0 R 600 0 R 601 0 R ] >> endobj 580 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/h1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 606 0 R /BBox [177.54 492.211 373.225 539.178] /Resources << /ProcSet [ /PDF /Text ] /Font << /F7 608 0 R /F8 610 0 R /F11 612 0 R /F14 614 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 615 0 R /Pat96 616 0 R >>>> /Length 371 /Filter /FlateDecode >> stream xڕS=O1 +> endobj 608 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 607 0 R >> endobj 610 0 obj << /Type /Font /Subtype /Type1 /FirstChar 40 /LastChar 61 /Widths [ 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 609 0 R >> endobj 612 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 120 /Widths [ 571.5] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 611 0 R >> endobj 614 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 613 0 R >> endobj 615 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 616 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 613 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 611 0 obj << /Type /Encoding /Differences [120/x] >> endobj 609 0 obj << /Type /Encoding /Differences [40/parenleft/parenright 48/zero/one/two 61/equal] >> endobj 607 0 obj << /Type /Encoding /Differences [50/two] >> endobj 581 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/h2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 617 0 R /BBox [144 288.34 255.287 335.596] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 619 0 R /F7 621 0 R /F8 623 0 R /F11 625 0 R /F14 627 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 628 0 R /Pat96 629 0 R >>>> /Length 511 /Filter /FlateDecode >> stream xڵTn0 XRDj Ȗk P4C4_:_l3lY"H{=)FT|ɡq;I |CG3B1;\O~k;(|܍u|}:.X,"e4ś'@q"Bz@` $ LF!;b- )v!@.l*f :4@f_,`IYmg7 !U!qayb4б("DGeilܻ,&MDRFf 6!&d$Yw"dJ)J4}5s~xd( P е;?(xd2~~]4:a:N؄]63,@OsvtS(gV޽qҒ(F Ҁu}XfOTURjkOY-  endstream endobj 617 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130206152453) /ModDate (D:20130206173131) >> endobj 619 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 53 /Widths [ 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 618 0 R >> endobj 621 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 620 0 R >> endobj 623 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 50 /Widths [ 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 622 0 R >> endobj 625 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 120 /Widths [ 571.5] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 624 0 R >> endobj 627 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 626 0 R >> endobj 628 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 629 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 626 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 624 0 obj << /Type /Encoding /Differences [120/x] >> endobj 622 0 obj << /Type /Encoding /Differences [48/zero/one/two] >> endobj 620 0 obj << /Type /Encoding /Differences [50/two] >> endobj 618 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt] >> endobj 582 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation16) >> >> endobj 583 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 584 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation18) >> >> endobj 585 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation16) >> >> endobj 586 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation17) >> >> endobj 587 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation18) >> >> endobj 588 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation19) >> >> endobj 589 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 590 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 591 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 592 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 593 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 594 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 595 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 596 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 597 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 598 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 599 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 600 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 601 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 579 0 obj << /D [603 0 R /XYZ 28.346 0 null] >> endobj 602 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F39 78 0 R /F40 605 0 R /F21 79 0 R >> /XObject << /Im18 580 0 R /Im19 581 0 R >> /ProcSet [ /PDF /Text ] >> endobj 654 0 obj << /Length 1072 /Filter /FlateDecode >> stream xXr7+p$;|L%r9)-Q+\Ryq,y/~aJZHl!'-e B;EA["VNrqvd䔣`C8%6&iP(x.KsԚ' `ƿE< (aII71v9/?k[WOc&|Uy:}fIQW-AXFN*kVF-ڬzjV?77n{{rr}-c+wiD ? _H+ʮ6 W d zQ鎂nl hBR0Ҩt'T.nFkPs=y ~~]qiK]'*).؏PdĤX2Zn'z|AٳuiYGٶv-{s}]j\#?U4qJ}R^~n艭LbE/? !HAцKJl>?9,hlg#>ĩq+>8I_|}S/ǀv| A_g y6λXPt V܉dSzϬѤd}}.g*384ލ$xl"9q퀔$עB!-ގC* oMlDf''a|-ɹ*"O8]Vs",2a%*ڻ*~9'ƺH/5VSaI6z0ٿ!-US؇T]bl9S㭠xu*̇(i#2Ye<%}PJ֏Eo\R!KzܮF=ghuN*JriC.46I}UT:tMhh]E47+Q(j8}x T K2pg;_ؐ_5Na2IMQoU{kjs^t3iIvyy]96kOW>$IaLOFմxH(LfؿBW endstream endobj 653 0 obj << /Type /Page /Contents 654 0 R /Resources 652 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 451 0 R /Annots [ 632 0 R 633 0 R 634 0 R 635 0 R 636 0 R 637 0 R 638 0 R 639 0 R 640 0 R 641 0 R 642 0 R 643 0 R 644 0 R 645 0 R 646 0 R 647 0 R 648 0 R 649 0 R 650 0 R 651 0 R ] >> endobj 632 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation17) >> >> endobj 633 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 634 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation19) >> >> endobj 635 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation16) >> >> endobj 636 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation17) >> >> endobj 637 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation18) >> >> endobj 638 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation19) >> >> endobj 639 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 640 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 641 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 642 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 643 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 644 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 645 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 646 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 647 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 648 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 649 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 650 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 651 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 630 0 obj << /D [653 0 R /XYZ 28.346 0 null] >> endobj 652 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F39 78 0 R /F40 605 0 R /F21 79 0 R >> /XObject << /Im18 580 0 R /Im19 581 0 R >> /ProcSet [ /PDF /Text ] >> endobj 677 0 obj << /Length 699 /Filter /FlateDecode >> stream xWKO1W19`fjAFɥzGMPi3;GQ)=t<ˣه% laXqEdяu}S\%xUSGpu[ȧ7):$NA>pʐ+ I662{%ƈ*(+ ,Q^89Z\d.4DoAe 24f>JD5CBSߛ^ }}Iu` ޵CC\ u8mSZ}=޶\?F`~]n^BR"ոj=M4kMX(nGڇMfUM6 #o&fyUhq endstream endobj 676 0 obj << /Type /Page /Contents 677 0 R /Resources 675 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 678 0 R /Annots [ 655 0 R 656 0 R 657 0 R 658 0 R 659 0 R 660 0 R 661 0 R 662 0 R 663 0 R 664 0 R 665 0 R 666 0 R 667 0 R 668 0 R 669 0 R 670 0 R 671 0 R 672 0 R 673 0 R 674 0 R ] >> endobj 655 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation18) >> >> endobj 656 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 657 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 658 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation18) >> >> endobj 659 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation19) >> >> endobj 660 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation19) >> >> endobj 661 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 662 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 663 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 664 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 665 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 666 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 667 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 668 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 669 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 670 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 671 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 672 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 673 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 674 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 631 0 obj << /D [676 0 R /XYZ 28.346 0 null] >> endobj 675 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im7 107 0 R >> /ProcSet [ /PDF /Text ] >> endobj 702 0 obj << /Length 1196 /Filter /FlateDecode >> stream xXKo6W(wo t{p%1j)HM^Lq479=0`F$ḮaO>-3VȄ\n}TbX>-1j*!Hqլez-?ż*];kXVO7Wn(Ր"2;@Z V5B[?|5ʁ<< C @'+evc`*awE3GIuDg2;zyŀKؗuU-5mQQѵΛf SP\$l&p45av=v:rYO9XyhJ:V*.zYBW6tgn 3)Rϒ㌧U7cBO8n 1dsᄻJ%>e,֙QP6 3+V ^9\xJ.^0b{AF/G9wϔs.qI-K9B@/?j]tJ)y-V[(6Oؐa(ݵ+?/n뿦^R|ӪVv(']04x{Bf!(9ey^YnB''U wf Ԛ|k!H*G$9db/=f;}zׄX(}08}X!`†ϩUW8 wwhaNݽ]/rһa;zn* "_1> /Parent 678 0 R /Annots [ 680 0 R 681 0 R 682 0 R 683 0 R 684 0 R 685 0 R 686 0 R 687 0 R 688 0 R 689 0 R 690 0 R 691 0 R 692 0 R 693 0 R 694 0 R 695 0 R 696 0 R 697 0 R 698 0 R 699 0 R ] >> endobj 680 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation19) >> >> endobj 681 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 682 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation21) >> >> endobj 683 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation19) >> >> endobj 684 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 685 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 686 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation21) >> >> endobj 687 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 688 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 689 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 690 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 691 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 692 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 693 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 694 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 695 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 696 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 697 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 698 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 699 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 679 0 obj << /D [701 0 R /XYZ 28.346 0 null] >> endobj 700 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F30 703 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 730 0 obj << /Length 723 /Filter /FlateDecode >> stream xWKO1W1bfZǪ-*&]DMA;KA)*y;&1wF*ъ&G[J.&( grނN8/O7nfuufofC~l/f2M|v}ZM?%  N/E )ڎU9w,oʬ*L{Lioc]1#p|'X oNra%;2dbpJP3 ]&GIS~ptl*?ǐ1RBtx4qB*V= f2K Mx WySF10dy$G;(,=O*'NW!!?~ mg>x997e2qWX8i BjDK8P!D!H SLlESӛ3ۇPX*?%>ot!\3ˈcmc˺]ZlͻݖKd6"еM.%e|ʢ:+S%`1^S&V|h/ĔgUhHɸ2/C-}k endstream endobj 729 0 obj << /Type /Page /Contents 730 0 R /Resources 728 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 678 0 R /Annots [ 708 0 R 709 0 R 710 0 R 711 0 R 712 0 R 713 0 R 714 0 R 715 0 R 716 0 R 717 0 R 718 0 R 719 0 R 720 0 R 721 0 R 722 0 R 723 0 R 724 0 R 725 0 R 726 0 R 727 0 R ] >> endobj 705 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/f4bunch.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 731 0 R /BBox [79.8 266.384 336.2 475.15] /Resources << /ProcSet [ /PDF /Text ] /Font << /F7 733 0 R /F8 735 0 R /F11 737 0 R /F15 740 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 741 0 R /Pat96 742 0 R >>>> /Length 912 /Filter /FlateDecode >> stream xWMo9q4+.7`nC!d5IIyntI߈"Er=+\c͏߻\uR1Y17ObS3l ud-|8Y\C;秣G.YGc1#G0:>Qy&K1i^77gAN9PJզ{/)Tf%6݇g |Tdu dٙ5/w g3g[Â.(H#;Aj͒<9-p&VqFY3meGhX Q`*6&h ʃ\ݜaaVo/{ܜ?/.O#$A> endobj 733 0 obj << /Type /Font /Subtype /Type1 /FirstChar 49 /LastChar 51 /Widths [ 569.5 569.5 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 732 0 R >> endobj 735 0 obj << /Type /Font /Subtype /Type1 /FirstChar 43 /LastChar 119 /Widths [ 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 734 0 R >> endobj 737 0 obj << /Type /Font /Subtype /Type1 /FirstChar 112 /LastChar 114 /Widths [ 503.1 446.4 451.2] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 736 0 R >> endobj 740 0 obj << /Type /Font /Subtype /Type1 /FirstChar 46 /LastChar 121 /Widths [ 319.4 575 575 575 575 575 575 575 575 575 575 575 319.4 319.4 350 894.4 543.1 543.1 894.4 869.4 818.1 830.6 881.9 755.6 723.6 904.2 900 436.1 594.4 901.4 691.7 1091.7 900 863.9 786.1 863.9 862.5 638.9 800 884.7 869.4 1188.9 869.4 869.4 702.8 319.4 602.8 319.4 575 319.4 319.4 559 638.9 511.1 638.9 527.1 351.4 575 638.9 319.4 351.4 606.9 319.4 958.3 638.9 575 638.9 606.9 473.6 453.6 447.2 638.9 606.9 830.6 606.9 606.9] /FontDescriptor 738 0 R /BaseFont 743 0 R /Encoding 739 0 R >> endobj 741 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 742 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 739 0 obj << /Type /Encoding /Differences [46/period/slash 97/a 99/c/d/e 103/g 105/i 108/l/m/n/o 114/r/s/t/u 120/x/y] >> endobj 736 0 obj << /Type /Encoding /Differences [112/p 114/r] >> endobj 734 0 obj << /Type /Encoding /Differences [43/plus 97/a/b/c 101/e/f 104/h/i 109/m/n/o 114/r/s/t 119/w] >> endobj 732 0 obj << /Type /Encoding /Differences [49/one/two/three] >> endobj 708 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 709 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 710 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation22) >> >> endobj 711 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 712 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation21) >> >> endobj 713 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation23) >> >> endobj 714 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation24) >> >> endobj 715 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 716 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 717 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 718 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 719 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 720 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 721 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 722 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 723 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 724 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 725 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 726 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 727 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 704 0 obj << /D [729 0 R /XYZ 28.346 0 null] >> endobj 728 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im20 705 0 R >> /ProcSet [ /PDF /Text ] >> endobj 769 0 obj << /Length 1035 /Filter /FlateDecode >> stream xXKo7W(mR$-A];JJi\>$-AӤ!+^3.d$PSVr Nrnث3ǎ߯O3<@lɍLjÅl}^.~sks=Y ڇovjP.oo-7CnߍĴ}F3\i+Ɂl`?3Yxl;-R$362ϭul~B̙MS3&ŜM 5 m>3g'M(,csyZh2zI\8*,?r몵O\=< /I0r*u:>J-W/߯[3 a=nvqoo7P1߂'/.qU= ccÜKR-Z3E{Hs˜ARYvd-O+lGA:nά+ Y Nd549N81C< pZ}G'xp .q$TXr(dbb4Vpу1)%;O FRDqVEJQB +2s$b@ ɰ@3qb^ j!}PJQ R5)]N^K\6 "oi6> I`}[SJdJ?K(U <ШsH O/һYovz^he**.FJ!|- MUZS0p(zQ(͢,V=-+3OhO NDp d}D(&ណ#dtU46xYWZÎ/:z=t4I6-)%⩋f?U8\E=^4U}T@|e%EVg endstream endobj 768 0 obj << /Type /Page /Contents 769 0 R /Resources 767 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 678 0 R /Annots [ 747 0 R 748 0 R 749 0 R 750 0 R 751 0 R 752 0 R 753 0 R 754 0 R 755 0 R 756 0 R 757 0 R 758 0 R 759 0 R 760 0 R 761 0 R 762 0 R 763 0 R 764 0 R 765 0 R 766 0 R ] >> endobj 706 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/s1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 771 0 R /BBox [155.891 293.934 435.549 418.652] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 773 0 R /F7 775 0 R /F8 777 0 R /F11 779 0 R /F14 781 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 782 0 R /Pat96 783 0 R >>>> /Length 919 /Filter /FlateDecode >> stream xXKO0WTZ3c{+RčvoA(]Ȇt7KyI q3?qfӐY {N,67'/9٨U,?'d͑BT3YL&fǤ00lh:]FCRfkjks ͈ b* X`Zy&1iRmlTMft{+9HT,`x\}ftYJXz eF -AJK/( /#CWb9͍b pA؂(R>M.;A߼갱1{#6R"̤/#Ll)( :9XSa\y 8`PԐD~(||:"F0gg!I̸%׎9e$^ybx+Izf~;?=QG9pEmkEB?2DyhX4q> endobj 773 0 obj << /Type /Font /Subtype /Type1 /FirstChar 20 /LastChar 53 /Widths [ 527.8 527.8 583.3 583.3 583.3 583.3 750 750 750 750 1044.4 1044.4 791.7 791.7 583.3 583.3 638.9 638.9 638.9 638.9 805.6 805.6 805.6 805.6 1277.8 1277.8 811.1 811.1 875 875 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 772 0 R >> endobj 775 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 51 /Widths [ 569.5 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 774 0 R >> endobj 777 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 119 /Widths [ 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 776 0 R >> endobj 779 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 778 0 R >> endobj 781 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 780 0 R >> endobj 782 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 783 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 780 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 778 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 776 0 obj << /Type /Encoding /Differences [48/zero/one/two 97/a 99/c/d/e/f 105/i 107/k/l/m/n/o 114/r/s/t/u 119/w] >> endobj 774 0 obj << /Type /Encoding /Differences [50/two/three] >> endobj 772 0 obj << /Type /Encoding /Differences [20/bracketleftbigg/bracketrightbigg 50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt] >> endobj 747 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation21) >> >> endobj 748 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 749 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation23) >> >> endobj 750 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 751 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation21) >> >> endobj 752 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation23) >> >> endobj 753 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation24) >> >> endobj 754 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 755 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 756 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 757 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 758 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 759 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 760 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 761 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 762 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 763 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 764 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 765 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 766 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 744 0 obj << /D [768 0 R /XYZ 28.346 0 null] >> endobj 767 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F19 41 0 R /F57 770 0 R /F39 78 0 R /F21 79 0 R >> /XObject << /Im21 706 0 R >> /ProcSet [ /PDF /Text ] >> endobj 806 0 obj << /Length 724 /Filter /FlateDecode >> stream xWKO1W1bfZǪ-*&]DMA;KA)*y;&1wF*ъ&G[J.&( grނN8/O7nfuufofC~l/f2M|v}ZM?%  N/E )ڎU9w,oʬ*L{Lioc5bFDO> AqA*DdKve'$gfy 14 T9L2DGw؞U!c б2~1h9Tޭz2B#E+=e44*6&qi b`H F!x4% biIUPszN3WvA{I)Fbx^_p`*˦TxNPό+FGV?bVҲZ~S1o_@Iýu#^xҫ,Swg[|wP4Y{$ULOBFC~0@&|zMYE@k\AU!d-NڂR):T|Ⱥ-QR[pQ!; O@">]22Xزnq[banR?٫ ;tfKyI/59 $m XהI)bc:1eY)'z2L }m endstream endobj 805 0 obj << /Type /Page /Contents 806 0 R /Resources 804 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 678 0 R /Annots [ 784 0 R 785 0 R 786 0 R 787 0 R 788 0 R 789 0 R 790 0 R 791 0 R 792 0 R 793 0 R 794 0 R 795 0 R 796 0 R 797 0 R 798 0 R 799 0 R 800 0 R 801 0 R 802 0 R 803 0 R ] >> endobj 707 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/f4bunch2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 807 0 R /BBox [79.8 266.384 336.2 475.15] /Resources << /ProcSet [ /PDF /Text ] /Font << /F7 809 0 R /F8 811 0 R /F11 813 0 R /F15 815 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 816 0 R /Pat96 817 0 R >>>> /Length 1198 /Filter /FlateDecode >> stream xWMo7 ϯqbQ5@ 7=GvQj6@хCC P$רeS)aq=P"bau7XvMlC`r.ӯ{;|V mHYk]zi}eUSW/$0jD¦>%nIiS$Eltr.Swӎc}]uQoۘ7Hu .>l8U]OTAI\6dՖˮQu3J~NGZ'v P+I$3Jv:}d S&+| q؀DNɔI[΢j5ؗI:;?YjD)r5hc_+7ꆟ,GHqk' ⚨jզWYYJ&cVȬYZ>-^3RYV`gcG ,hm豣69gKy5;q+8؉} t9Z ܰsn=]8&cR5@|-+3Ѳ0HF|X4D#RUbE#{2I,.=-`"/w{~Hϱ"4RܔGgۣs8-^dz9OF\,Q}' N9#rLJdyRȵA=4$ܞXn7dE_FDŽOAGz(NJ,!z -zR5Y=>4Ɩ6}SV)Dq(jR@U̪i [淛0{_=>> endobj 809 0 obj << /Type /Font /Subtype /Type1 /FirstChar 49 /LastChar 51 /Widths [ 569.5 569.5 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 808 0 R >> endobj 811 0 obj << /Type /Font /Subtype /Type1 /FirstChar 43 /LastChar 119 /Widths [ 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 810 0 R >> endobj 813 0 obj << /Type /Font /Subtype /Type1 /FirstChar 112 /LastChar 114 /Widths [ 503.1 446.4 451.2] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 812 0 R >> endobj 815 0 obj << /Type /Font /Subtype /Type1 /FirstChar 46 /LastChar 121 /Widths [ 319.4 575 575 575 575 575 575 575 575 575 575 575 319.4 319.4 350 894.4 543.1 543.1 894.4 869.4 818.1 830.6 881.9 755.6 723.6 904.2 900 436.1 594.4 901.4 691.7 1091.7 900 863.9 786.1 863.9 862.5 638.9 800 884.7 869.4 1188.9 869.4 869.4 702.8 319.4 602.8 319.4 575 319.4 319.4 559 638.9 511.1 638.9 527.1 351.4 575 638.9 319.4 351.4 606.9 319.4 958.3 638.9 575 638.9 606.9 473.6 453.6 447.2 638.9 606.9 830.6 606.9 606.9] /FontDescriptor 738 0 R /BaseFont 743 0 R /Encoding 814 0 R >> endobj 816 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 817 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 814 0 obj << /Type /Encoding /Differences [46/period/slash 97/a 99/c/d/e 103/g 105/i 108/l/m/n/o 114/r/s/t/u 120/x/y] >> endobj 812 0 obj << /Type /Encoding /Differences [112/p 114/r] >> endobj 810 0 obj << /Type /Encoding /Differences [43/plus 97/a/b/c 101/e/f 104/h/i 109/m/n/o 114/r/s/t 119/w] >> endobj 808 0 obj << /Type /Encoding /Differences [49/one/two/three] >> endobj 784 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation22) >> >> endobj 785 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 786 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation24) >> >> endobj 787 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation20) >> >> endobj 788 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation21) >> >> endobj 789 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation23) >> >> endobj 790 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation24) >> >> endobj 791 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 792 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 793 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 794 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 795 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 796 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 797 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 798 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 799 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 800 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 801 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 802 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 803 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 745 0 obj << /D [805 0 R /XYZ 28.346 0 null] >> endobj 804 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im22 707 0 R >> /ProcSet [ /PDF /Text ] >> endobj 840 0 obj << /Length 1084 /Filter /FlateDecode >> stream xXKo8WQ,7rjߊ⭝")gI}3pX7~0"HgpF0'5+ n&;O.^s0V=\>Tڻ[L%Viէi-n6SɃ$,n7f޵/ UYڥU7jCS9N?//^K>NC9RI͞&2M1t"5nj(նҴېT[8Jk㙕&d۫_s!F3a%hM75=ΤwU<ኪO"S!B؝"C!E0B8znq]}MDoIl# c!*s0`(Bmoe֚<-(^ʭaFNke 7Jmy[bm-vt6 [4/EBg aSJN33)(IWB ƅ~$82JcÔERAra⇉3[v~4+JёHш'K$}t^) Ḵ_9fx,Q I+:N0('sAj+*,^RaAx|a5~o (wx송g2tw=KXxzy|xY<"j\R#KRΧF~HX1.TtPyn|P"6] g p(|uC\8.|:iswn@GQ9F^7%,)ifGP-~xW% {,9!n†,\HY8ؐS:vSxQꗟ vD/{? !%Ƹh#QΧX焳ڠ;Hʋ8|U1ؿԿQ89 endstream endobj 839 0 obj << /Type /Page /Contents 840 0 R /Resources 838 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 678 0 R /Annots [ 818 0 R 819 0 R 820 0 R 821 0 R 822 0 R 823 0 R 824 0 R 825 0 R 826 0 R 827 0 R 828 0 R 829 0 R 830 0 R 831 0 R 832 0 R 833 0 R 834 0 R 835 0 R 836 0 R 837 0 R ] >> endobj 818 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation23) >> >> endobj 819 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 820 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation25) >> >> endobj 821 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation23) >> >> endobj 822 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation24) >> >> endobj 823 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation25) >> >> endobj 824 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation26) >> >> endobj 825 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 826 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 827 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 828 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 829 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 830 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 831 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 832 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 833 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 834 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 835 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 836 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 837 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 746 0 obj << /D [839 0 R /XYZ 28.346 0 null] >> endobj 838 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F30 703 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 865 0 obj << /Length 1083 /Filter /FlateDecode >> stream xXKs6W쑚a,޸fɌOM[&eMDqzuռ|徾ohKnFiLaCa`k7[tyw` AgK‡Mwj;41f*y,ۇvej6USXmhm [QiQ3\{DLv Hzzۭ emo46d#R%?xf$>AcۜhG#LX h-3CM>|pK3@=L{].3jLsyj4Ψl-7E+Qr/02qHbrZkoMe ?/ y9{0qK8n`+f& ?HN8hO0qLZo9dY)ArVNAUnOBّ?j$RS /JDאu-h$2vn faef 0a3[v~4 J*"j\R%Kz)Y߮_'(k +TH2xCg!2.y+$*A"A(=çXM"KJ }  w7aCyzS$,Jtpl)}e{)(φ;pMhc\OY (Ss m$ES|yTbhKdLfy1 endstream endobj 864 0 obj << /Type /Page /Contents 865 0 R /Resources 863 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 866 0 R /Annots [ 843 0 R 844 0 R 845 0 R 846 0 R 847 0 R 848 0 R 849 0 R 850 0 R 851 0 R 852 0 R 853 0 R 854 0 R 855 0 R 856 0 R 857 0 R 858 0 R 859 0 R 860 0 R 861 0 R 862 0 R ] >> endobj 843 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation24) >> >> endobj 844 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 845 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation26) >> >> endobj 846 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation23) >> >> endobj 847 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation24) >> >> endobj 848 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation25) >> >> endobj 849 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation26) >> >> endobj 850 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 851 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 852 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 853 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 854 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 855 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 856 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 857 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 858 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 859 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 860 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 861 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 862 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 841 0 obj << /D [864 0 R /XYZ 28.346 0 null] >> endobj 863 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F30 703 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 890 0 obj << /Length 1240 /Filter /FlateDecode >> stream xXKs6WV cn3iɡ큡iHƔ.lq6nNϞK+Z!Ï1A:pT󜀠 ) Ya'3:$'b(זYAɅ )s8uRFe,$e+4Qx7$pH"_x L#T0qZϙC0MS BgsԠIGp"EP>ϑШ2'P|w NP#c(F## laFs3OF137n70=J'v&jqQ Qτ? ko|ٌ3O?̈}~D^hwLY4#IPPjG.dh16i^"I%^)8FD1 ILVFɋHInFwB):;G_\~e)ˈ/]=2Q02OQ~cM+j]e:y_\kwyJ6LSv!h,?I::!AxGJ3Iƃ2EŧQ%.bP+zGIյ}=,^7@^vxÈڄYK w aqGD6s1Z3WXyt/ʽ2m0)nSW/Lr hqe Όs8ZK~\ g?.WΪMhۢ|ww2̻yXة n8ʩAM9v1.@O5_ź3Z!ӭ>vs-znL#J BG߽.53yY]~BݶQTB쯞um Dt^,(;+) 3sCIYHެ ]l]|} ˮnbfQy߷;5´ t6_u]zTk~_|,+ Wݾ^K*[j %vXos* p{9(n ;J0yp}#?G}0i c@]B6OhTWfW'KXֽm>m TDW% endstream endobj 889 0 obj << /Type /Page /Contents 890 0 R /Resources 888 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 866 0 R /Annots [ 867 0 R 868 0 R 869 0 R 870 0 R 871 0 R 872 0 R 873 0 R 874 0 R 875 0 R 876 0 R 877 0 R 878 0 R 879 0 R 880 0 R 881 0 R 882 0 R 883 0 R 884 0 R 885 0 R 886 0 R 887 0 R ] >> endobj 867 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation25) >> >> endobj 868 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 869 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation27) >> >> endobj 870 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation25) >> >> endobj 871 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation26) >> >> endobj 872 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation26) >> >> endobj 873 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation27) >> >> endobj 874 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 875 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 876 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 877 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 878 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 879 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 880 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 881 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 882 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 883 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 884 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 885 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 886 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 887 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation1) >> >> endobj 842 0 obj << /D [889 0 R /XYZ 334.488 0 null] >> endobj 891 0 obj << /D [889 0 R /XYZ 334.488 0 null] >> endobj 888 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm1 12 0 R /Fm5 53 0 R >> /ProcSet [ /PDF /Text ] >> endobj 915 0 obj << /Length 902 /Filter /FlateDecode >> stream xWMs6WD 4CRPJn$׻  #MLx}xF#]kEŋGN:^?#*` XZ!9Шz ,4XNҸ|Y<]>QH3OTvxan5~;^y4ÊBjj8ݯq{E92AҢrHcaOc !y8h"3(+dMo"]QU5F6APuHWx?@XYWI4hDt{H6' #UT|;qeS89j$vw%gHOBңx"y$} EeN+D.)lsE%xHcZd@ ϩ0yC]˗6D}U})Bc(|'݀I&Y:,2px1\}%dOu.4m1N_0* HJΜwZspYgZSe$*CEڌ_Rf)T,4mV,3Q< g oپiI*RAC2> c Ӂ endstream endobj 914 0 obj << /Type /Page /Contents 915 0 R /Resources 913 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 866 0 R /Annots [ 893 0 R 894 0 R 895 0 R 896 0 R 897 0 R 898 0 R 899 0 R 900 0 R 901 0 R 902 0 R 903 0 R 904 0 R 905 0 R 906 0 R 907 0 R 908 0 R 909 0 R 910 0 R 911 0 R 912 0 R ] >> endobj 893 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation26) >> >> endobj 894 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 895 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation28) >> >> endobj 896 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation26) >> >> endobj 897 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation27) >> >> endobj 898 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation27) >> >> endobj 899 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation28) >> >> endobj 900 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 901 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 902 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 903 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 904 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 905 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 906 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 907 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 908 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 909 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 910 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 911 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 912 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 892 0 obj << /D [914 0 R /XYZ 28.346 0 null] >> endobj 913 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 940 0 obj << /Length 725 /Filter /FlateDecode >> stream xWKO1W}ڢ"@ɭZA"M;DPJ!y~c @8H<?A0^hiON:N?RB0Li9Pt0={^Y\ʂ߻\ϗ7~{?fg7luv~j=./oɇ)י#Q)t Fc{?9 *~q):O~Zh,)ax @( p4 +9dvxe$IT3<R@L g%B[{ l- d!t) ]+s lXذqꮋf/44﯈*r"<#QzH(q,b6AJz'(+4J@Gs:ʥee"g͜⬷|c."Z*" *B|DKMqCf!HMS\li2XnsyCwzW ;M8>ŗx]=u̵;t;/H%.ROZ I>Z$ Y!CS}l~y&EBbOIYJS endstream endobj 939 0 obj << /Type /Page /Contents 940 0 R /Resources 938 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 866 0 R /Annots [ 918 0 R 919 0 R 920 0 R 921 0 R 922 0 R 923 0 R 924 0 R 925 0 R 926 0 R 927 0 R 928 0 R 929 0 R 930 0 R 931 0 R 932 0 R 933 0 R 934 0 R 935 0 R 936 0 R 937 0 R ] >> endobj 917 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/abcd1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 941 0 R /BBox [147.771 535.602 430.387 608.094] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 943 0 R /F8 945 0 R /F11 947 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 948 0 R /Pat96 949 0 R >>>> /Length 684 /Filter /FlateDecode >> stream xWMo@ﯘcagg?7 ԴT%8N\$YZ)v>Z&FkB V۝O _1!:ԑdW]&o<ĵޝ/b 7>\}E-r 낃eqʖ`#> cВ c^1a4~v0!j.AA%Pi[B1ȵі6?D [ԡBDpV . F$[eוϘ_{R̡rg%"gS" mia*Pk4}i}ZQ1VUQvd-Fa+&)trIRKDH{7m$f>d_,E)SL$pP5,RTNDKRUQ(Q2Mq?(yIm}.tu\",{=}PN2h.J+Q[Q #Cm ;a #4nN%ގ* Isav$p(H> endobj 943 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 942 0 R >> endobj 945 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 117 /Widths [ 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 944 0 R >> endobj 947 0 obj << /Type /Font /Subtype /Type1 /FirstChar 65 /LastChar 68 /Widths [ 750 758.5 714.7 827.9] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 946 0 R >> endobj 948 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 949 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 946 0 obj << /Type /Encoding /Differences [65/A/B/C/D] >> endobj 944 0 obj << /Type /Encoding /Differences [48/zero/one/two/three/four/five/six/seven 57/nine 97/a 99/c/d/e 104/h 110/n/o 114/r/s 117/u] >> endobj 942 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 918 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation27) >> >> endobj 919 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 920 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation29) >> >> endobj 921 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation27) >> >> endobj 922 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation28) >> >> endobj 923 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation28) >> >> endobj 924 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation29) >> >> endobj 925 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 926 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 927 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 928 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 929 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 930 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 931 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 932 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 933 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 934 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 935 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 936 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 937 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 916 0 obj << /D [939 0 R /XYZ 28.346 0 null] >> endobj 938 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im23 917 0 R >> /ProcSet [ /PDF /Text ] >> endobj 974 0 obj << /Length 693 /Filter /FlateDecode >> stream xWKS1ϯrНw"J wo!UhNf:v@DItJ t5wF*:hE\vg;J{@&%ڐi877b{f:*c=3" O53J椸$gUh|ۇmxñb'F-IB27IIy2va)C&E D=wC H`,DrVНehaIv1U!R00SFtx4p*MbAh(Bsѷ3wS$kyTJW)c}I *|8AғDyJzF:M<҃O/",vrH">_: سny.aؾ}mOZ/:zl|YRKSXğ- y BmHT/GUhHqe2^ Fo endstream endobj 973 0 obj << /Type /Page /Contents 974 0 R /Resources 972 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 866 0 R /Annots [ 952 0 R 953 0 R 954 0 R 955 0 R 956 0 R 957 0 R 958 0 R 959 0 R 960 0 R 961 0 R 962 0 R 963 0 R 964 0 R 965 0 R 966 0 R 967 0 R 968 0 R 969 0 R 970 0 R 971 0 R ] >> endobj 951 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/abcd2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 975 0 R /BBox [154.843 432.768 428.025 524.332] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 977 0 R /F8 979 0 R /F11 981 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 982 0 R /Pat96 983 0 R >>>> /Length 560 /Filter /FlateDecode >> stream xڵMo0 <u\շa+xC3 ɖ'̗K3Vp 3(IG(o4_cZFFӄl'(g|W<'ؼ7)ԂLt#1FFkQk/VQ+mWlCw^|P_9fm>kcԃ8z˿Y&O> endobj 977 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 976 0 R >> endobj 979 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 117 /Widths [ 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 978 0 R >> endobj 981 0 obj << /Type /Font /Subtype /Type1 /FirstChar 65 /LastChar 68 /Widths [ 750 758.5 714.7 827.9] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 980 0 R >> endobj 982 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 983 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 980 0 obj << /Type /Encoding /Differences [65/A/B/C/D] >> endobj 978 0 obj << /Type /Encoding /Differences [48/zero/one/two/three/four/five/six/seven 57/nine 97/a 99/c/d/e 104/h 110/n/o 114/r/s 117/u] >> endobj 976 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 952 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation28) >> >> endobj 953 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 954 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation30) >> >> endobj 955 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation28) >> >> endobj 956 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation29) >> >> endobj 957 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation29) >> >> endobj 958 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation30) >> >> endobj 959 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 960 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 961 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 962 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 963 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 964 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 965 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 966 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 967 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 968 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 969 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 970 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 971 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 950 0 obj << /D [973 0 R /XYZ 28.346 0 null] >> endobj 972 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im24 951 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1008 0 obj << /Length 717 /Filter /FlateDecode >> stream xWKO1W1{תBɭm!T"E{w%DPJ!,9 X]$aK*aaW)vqf* C#Fخa|T]P*xNr&0'{2dRtp Y%*R^ ) Q&U1\Sdha|$;Dw؞U?ǐM)Eذ:^p<F^զG 4Q(lX".֤;#-!F,b'ʯA4O18c) @d}eFqҠ~NQB*% G+n [*qLEonڞ|$G,J6 8,6WP'`9^&K\ޖ!=TMFЧ,,Q0 3֜/2ָȭB,\!.j[Sry_)&e;e\ E*}@wz_ά =&vi%vv_ְ@^~n6$_TR(IsV!jKbD!6~h/뤜fUhHȸ{3c~wc endstream endobj 1007 0 obj << /Type /Page /Contents 1008 0 R /Resources 1006 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 866 0 R /Annots [ 986 0 R 987 0 R 988 0 R 989 0 R 990 0 R 991 0 R 992 0 R 993 0 R 994 0 R 995 0 R 996 0 R 997 0 R 998 0 R 999 0 R 1000 0 R 1001 0 R 1002 0 R 1003 0 R 1004 0 R 1005 0 R ] >> endobj 985 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/abcd3.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 1009 0 R /BBox [4.58053 326.976 289.071 508.587] /Resources << /ProcSet [ /PDF /Text ] /Font << /F8 1011 0 R /F11 1013 0 R /F13 1016 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 1017 0 R /Pat96 1018 0 R >>>> /Length 1219 /Filter /FlateDecode >> stream xXMo6W,oM- {itGQQFlp\,#9Cμ=JħPҊ+%*Hc8'QB-"mQܼe0$l ҥlb#J(v˜wG2–a]0.$G058#T5`XI1Xݬ~"glO/+uAWwoI-ה4&soy$}~[>LN#I)Yƒ>t#HFL~ݜu9N_+wMɠcԡ!ȶzFcL00'$mJg$"*!|vͱwvQ&r \=s4Ch@X9MLs?dG|8Q~( 'y!:l5ʺҮZj#lzmr%WH=ϔiԉ9)Oa .!(|rJ&] 9%|x%EkH߸2:'#jAWK3L{iN [,Ya0Mj 4r+ &j|B dK fhDXoyFFKHvof$Aɱ||ѡ^#L4r%;r[戗_ ajjl7Mu8d߾Cf|#rO(|lu{4IX{U&IcNI0ZB" 5åww> endobj 1011 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 121 /Widths [ 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 1010 0 R >> endobj 1013 0 obj << /Type /Font /Subtype /Type1 /FirstChar 59 /LastChar 68 /Widths [ 277.8 777.8 500 777.8 500 530.9 750 758.5 714.7 827.9] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 1012 0 R >> endobj 1016 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 48 /Widths [ 329.4] /FontDescriptor 1014 0 R /BaseFont 1019 0 R /Encoding 1015 0 R >> endobj 1017 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1018 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1015 0 obj << /Type /Encoding /Differences [48/prime] >> endobj 1012 0 obj << /Type /Encoding /Differences [59/comma 65/A/B/C/D] >> endobj 1010 0 obj << /Type /Encoding /Differences [48/zero/one 67/C 98/b/c/d/e/f 105/i 108/l/m/n/o/p 114/r/s/t/u 121/y] >> endobj 986 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation29) >> >> endobj 987 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 988 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation31) >> >> endobj 989 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation29) >> >> endobj 990 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation30) >> >> endobj 991 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation30) >> >> endobj 992 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation31) >> >> endobj 993 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 994 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 995 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 996 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 997 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 998 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 999 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1000 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1001 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1002 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1003 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1004 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1005 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 984 0 obj << /D [1007 0 R /XYZ 28.346 0 null] >> endobj 1006 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im25 985 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1044 0 obj << /Length 871 /Filter /FlateDecode >> stream xWKS0W9Dh%Y}1'Jfz`z84NhjߕC@)S ",! $" N*%PY5Qzf::P /=tΊ ɑFaLpYݶ7]3h[2nl[]-M&gc-ln3rdMJ'0Q'W_6|V]l]iybu=ůH2H#u6Jo"&Ei *E ]pIQ՜um!z71v>"ͬ^&mc(& [͌!B6z JH1C}q{ag܄u8+8@>f/h@Z;p&Aڻ~BPqBY%VZhWi P\hՄ,(" +.&Jrط gcEAV|B#-c9 SNX[[$kEߝ#TFv2@aWW%> /Parent 1045 0 R /Annots [ 1022 0 R 1023 0 R 1024 0 R 1025 0 R 1026 0 R 1027 0 R 1028 0 R 1029 0 R 1030 0 R 1031 0 R 1032 0 R 1033 0 R 1034 0 R 1035 0 R 1036 0 R 1037 0 R 1038 0 R 1039 0 R 1040 0 R 1041 0 R ] >> endobj 1021 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/abcd4.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 1046 0 R /BBox [187.519 427.496 369.072 497.797] /Resources << /ProcSet [ /PDF /Text ] /Font << /F8 1048 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 1049 0 R /Pat96 1050 0 R >>>> /Length 525 /Filter /FlateDecode >> stream xڵUN0 +y9"Hݍf1W{ $~'m4,DǏFhճ62I~t˓.Q{&L rGeSrv&U&B>! }E0lX2[57ZWd(DcA Q;U73W>Uʖ}}}nDVyߥ!8`aKԝDHL=۲fҞh΃wgFjPj ٭3wmϲ>L07Nfѓ3*F!x,M)3Z:`R2쀼'e[,1-2k)k[vHS%@v+BdjF22R$ZIgwYdBNY0ҝN 2Cjʧ Rggu9I3pex:ܫg9nLy58`8:7kkq(w>F~εSA X’^}6HfyDpY endstream endobj 1046 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130208173232) /ModDate (D:20130208183522) >> endobj 1048 0 obj << /Type /Font /Subtype /Type1 /FirstChar 49 /LastChar 116 /Widths [ 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 1047 0 R >> endobj 1049 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1050 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1047 0 obj << /Type /Encoding /Differences [49/one/two/three 97/a 100/d/e 104/h 114/r 116/t] >> endobj 1022 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation30) >> >> endobj 1023 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1024 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation32) >> >> endobj 1025 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation30) >> >> endobj 1026 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation31) >> >> endobj 1027 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation31) >> >> endobj 1028 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation32) >> >> endobj 1029 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1030 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1031 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1032 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1033 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1034 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1035 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1036 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1037 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1038 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1039 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1040 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1041 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1020 0 obj << /D [1043 0 R /XYZ 28.346 0 null] >> endobj 1042 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Im26 1021 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1075 0 obj << /Length 795 /Filter /FlateDecode >> stream xWV1IG'T!v$Y ^H.pB#].@@nI$$^W,\|pcPz28|P B%Ԡgr_ӃlFCk< p9mlŪYgroc caF _9)'d9$9zHaqdMFɣzqLz:U^I!O!Uip7?ji=݄#%k  u\FW0ч=N W ZuI-wOJ(08V@LBّ?#$U%y*XG&ЊQ!+ sn3J̟"۾qVC]# O)z IztrqjDA4v +SWX0*g9H=AGc:,E4 )@Yɖ*Cϛ®ߖΗq7ȴ=^]D}/qyyeZ?>;Gd-ǒ6yߓ@$]k% ҆̐XɐmLzgkK=BEr % FJbOWޘ>UBzLtBuATIv6-;ٮJx@u7z9imb.S&]q>Śf]InM!R /|Xg7y endstream endobj 1074 0 obj << /Type /Page /Contents 1075 0 R /Resources 1073 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1045 0 R /Annots [ 1053 0 R 1054 0 R 1055 0 R 1056 0 R 1057 0 R 1058 0 R 1059 0 R 1060 0 R 1061 0 R 1062 0 R 1063 0 R 1064 0 R 1065 0 R 1066 0 R 1067 0 R 1068 0 R 1069 0 R 1070 0 R 1071 0 R 1072 0 R ] >> endobj 1052 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/abcd5.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 1076 0 R /BBox [287.4 319.4 416.6 416.6] /Resources << /ProcSet [ /PDF /Text ] /Font << /F8 1078 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 1079 0 R /Pat96 1080 0 R >>>> /Length 255 /Filter /FlateDecode >> stream xڍ1 EwNCRݪU zb!!Wx|po;;% .}) =7(۬.ד7sn eicSb=̦|VBq$5s1LAynYi1 g,]״J ִJ *6p*V{-G'S@RQ@RRX#wGxP=gּ{ԮLn-8|?H endstream endobj 1076 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130208173232) /ModDate (D:20130211161214) >> endobj 1078 0 obj << /Type /Font /Subtype /Type1 /FirstChar 12 /LastChar 117 /Widths [ 555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 750 444.4 500 722.2 777.8 500 902.8 1013.9 777.8 277.8 277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 1077 0 R >> endobj 1079 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1080 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1077 0 obj << /Type /Encoding /Differences [12/fi 39/quoteright 67/C 69/E 80/P 85/U 97/a 99/c 101/e 104/h/i 110/n 113/q/r/s/t/u] >> endobj 1053 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation31) >> >> endobj 1054 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1055 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation33) >> >> endobj 1056 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation31) >> >> endobj 1057 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation32) >> >> endobj 1058 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation32) >> >> endobj 1059 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation33) >> >> endobj 1060 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1061 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1062 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1063 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1064 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1065 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1066 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1067 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1068 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1069 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1070 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1071 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1072 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1051 0 obj << /D [1074 0 R /XYZ 28.346 0 null] >> endobj 1073 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Im27 1052 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1104 0 obj << /Length 1045 /Filter /FlateDecode >> stream xWM6W(pknmzH׷4CzmDȏ#%Rڤ"_{XO37o"-ؒ j"FHLYɽ2L:IZֵ~KǗɋ"3VIr\[f znVTuSe]u8կͧ\Jr)Ԧ9]3 b"(U>5FR2J@"|z֬'o [& ,Zq{dwP؞0$ QPH}H9DTOI1G瀺g-=Sj'O~/Q'eqkLUAtY(ev("C\b"t!w:*>H7OӵĽg4 HD:m"{#\;??òCHYk'k<ݾk{ lqF>"A !t䘍{nn,za OS!.EHc$݁iEDѸ1/2Bߠߣ9,f! `%勪%SC*9:vH0L7=w\'Gq8#eP/uOb\KJ?eI+|j qPKzp0GYoq9y@ /2ɷ!"MApUBS)kySXd!.RiC3woٸb 9+X! Ys՛WDL|l)c{),;xM%ɦ)uɥ|d\@O΄s1%\)Y+:NbLE` endstream endobj 1103 0 obj << /Type /Page /Contents 1104 0 R /Resources 1102 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1045 0 R /Annots [ 1082 0 R 1083 0 R 1084 0 R 1085 0 R 1086 0 R 1087 0 R 1088 0 R 1089 0 R 1090 0 R 1091 0 R 1092 0 R 1093 0 R 1094 0 R 1095 0 R 1096 0 R 1097 0 R 1098 0 R 1099 0 R 1100 0 R 1101 0 R ] >> endobj 1082 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation32) >> >> endobj 1083 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1084 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation34) >> >> endobj 1085 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation32) >> >> endobj 1086 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation33) >> >> endobj 1087 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation33) >> >> endobj 1088 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation34) >> >> endobj 1089 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1090 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1091 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1092 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1093 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1094 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1095 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1096 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1097 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1098 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1099 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1100 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1101 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1081 0 obj << /D [1103 0 R /XYZ 28.346 0 null] >> endobj 1102 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1129 0 obj << /Length 1240 /Filter /FlateDecode >> stream xXKs6WV cn3iɡ큡iHƔ.lq6nNϞK+Z!Ï1A:pT󜀠 ) Ya'3:$'b(זYAɅ )s8uRFe,$e+4Qx7$pH"_x L#T0qZϙC0MS BgsԠIGp"EP>ϑШ2'P|w NP#c(F## laFs3OF137n70=J'v&jqQ Qτ? ko|ٌ3O?̈}~D^hwLY4#IPPjG.dh16i^"I%^)8FD1 ILVFɋHInFwB):;G_\~e)ˈ/]=2Q02OQ~cM+j]e:y_\kwyJ6LSv!h,?I::!AxGJ3Iƃ2EŧQ%.bP+zGIյ}=,^7@^vxÈڄYK w aqGD6s1Z3WXyt/ʽ2m0)nSW/Lr hqe Όs8ZK~\ g?.WΪMhۢ|ww2̻yXة n8ʩAM9v1.@O5_ź3Z!ӭ>vs-znL#J BG߽.53yY]~BݶQTB쯞um Dt^,(;+) 3sCIYHެ ]l]|} ˮnbfQy߷;5´ t6_u]zTk~_|,+ Wݾ^K*[j %vXos* p{9(n ;J0yp}#?G}0i c@]B6OhTWfW'KXֽm>m TDW% endstream endobj 1128 0 obj << /Type /Page /Contents 1129 0 R /Resources 1127 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1045 0 R /Annots [ 1106 0 R 1107 0 R 1108 0 R 1109 0 R 1110 0 R 1111 0 R 1112 0 R 1113 0 R 1114 0 R 1115 0 R 1116 0 R 1117 0 R 1118 0 R 1119 0 R 1120 0 R 1121 0 R 1122 0 R 1123 0 R 1124 0 R 1125 0 R 1126 0 R ] >> endobj 1106 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation33) >> >> endobj 1107 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 1108 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation35) >> >> endobj 1109 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation33) >> >> endobj 1110 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation34) >> >> endobj 1111 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation34) >> >> endobj 1112 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation35) >> >> endobj 1113 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1114 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1115 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1116 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1117 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1118 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1119 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1120 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1121 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1122 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1123 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 1124 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 1125 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 1126 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation1) >> >> endobj 1105 0 obj << /D [1128 0 R /XYZ 334.488 0 null] >> endobj 1130 0 obj << /D [1128 0 R /XYZ 334.488 0 null] >> endobj 1127 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm1 12 0 R /Fm5 53 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1154 0 obj << /Length 720 /Filter /FlateDecode >> stream xWQo1 ~_7r+LTBbocՍJ릕J}\ܺcv9E$$7 `Mt-6_9cPvѼyOMD8 A @gp24u4YNN6kɇbּ[p|!U˘Lg usrpƓ3@]Yu 6_/a4a[CβSo06!5K ~du}c%w"1GKYY a2>yt8!b˜$vCg\JtͱXE/ûpx_+yM)EiFl:δ,#R^gŌPƆCl*k챋 N\0sI㡤u#C%1E!!9F% h>Y?DyH.R'}LѴr|]KVz)T⎊:_nQtķ|Ejyr J<9"Kd]C?(܎Q% I F)@KB 29|pe܃\k c]/=ܚRˁ:K0*=|+~*9g{IZrE'U "/A,kݗ=&wiv_-ӹڰF`kG/g?o7/KRCRA]@OրyDV|h/$aeǬ!o&aoO{5 endstream endobj 1153 0 obj << /Type /Page /Contents 1154 0 R /Resources 1152 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1045 0 R /Annots [ 1132 0 R 1133 0 R 1134 0 R 1135 0 R 1136 0 R 1137 0 R 1138 0 R 1139 0 R 1140 0 R 1141 0 R 1142 0 R 1143 0 R 1144 0 R 1145 0 R 1146 0 R 1147 0 R 1148 0 R 1149 0 R 1150 0 R 1151 0 R ] >> endobj 1132 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation34) >> >> endobj 1133 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1134 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation36) >> >> endobj 1135 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation34) >> >> endobj 1136 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation35) >> >> endobj 1137 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation35) >> >> endobj 1138 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation36) >> >> endobj 1139 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1140 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1141 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1142 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1143 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1144 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1145 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1146 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1147 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1148 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1149 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1150 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1151 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1131 0 obj << /D [1153 0 R /XYZ 28.346 0 null] >> endobj 1152 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1178 0 obj << /Length 725 /Filter /FlateDecode >> stream xWKO1W19vU *ȭ!ZĂQ;KBy~c8@8H<?A0^`F++XON(=wRB1,u u9|lnC M63|]Ϳ.ۋt{]jsۋncqpO8+TX¨\lAE  m k*aHEwi7` uHbto#X}l%ME(xxD\Rz%})YnoKא&zSBF@&|Zsr[|ȼe.Z " sq҈nMqCmBxJ NM>zR~(Y|BЧYޥmA8<ֆ;qܥŖX=miOjN7];z9y|RKMΧLI> /Parent 1045 0 R /Annots [ 1156 0 R 1157 0 R 1158 0 R 1159 0 R 1160 0 R 1161 0 R 1162 0 R 1163 0 R 1164 0 R 1165 0 R 1166 0 R 1167 0 R 1168 0 R 1169 0 R 1170 0 R 1171 0 R 1172 0 R 1173 0 R 1174 0 R 1175 0 R ] >> endobj 1156 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation35) >> >> endobj 1157 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1158 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation37) >> >> endobj 1159 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation35) >> >> endobj 1160 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation36) >> >> endobj 1161 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation36) >> >> endobj 1162 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation37) >> >> endobj 1163 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1164 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1165 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1166 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1167 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1168 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1169 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1170 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1171 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1172 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1173 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1174 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1175 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1155 0 obj << /D [1177 0 R /XYZ 28.346 0 null] >> endobj 1176 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im25 985 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1203 0 obj << /Length 713 /Filter /FlateDecode >> stream xWKO1W̭3㷯U *RJR(!j;KB;^;p8-I,OF*:hE;O=UO(Jju u| M3_jg~.fq}nCK]"nqs̾͏&\P.@Ge-@R轟rN OKÊyx # a}[ȗUTć=}![&Qi|lH 2ЬDrN`rlcV!C6aɞ21ʱ4p/*͎bAhd(Jc>Ǚ.и"ΫLʵ.҂bdȲ$Gz8-_>d1q[x*B|WDKMqC]BWJ?V }m1R9gA7d}w l6_a{ow׵2|#D{,7C/C*q)zS%aqJuR?4mRJZ4.$dܽ^w] endstream endobj 1202 0 obj << /Type /Page /Contents 1203 0 R /Resources 1201 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1204 0 R /Annots [ 1181 0 R 1182 0 R 1183 0 R 1184 0 R 1185 0 R 1186 0 R 1187 0 R 1188 0 R 1189 0 R 1190 0 R 1191 0 R 1192 0 R 1193 0 R 1194 0 R 1195 0 R 1196 0 R 1197 0 R 1198 0 R 1199 0 R 1200 0 R ] >> endobj 1180 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/gauss1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 1205 0 R /BBox [4.58053 329.131 288.931 508.587] /Resources << /ProcSet [ /PDF /Text ] /Font << /F8 1207 0 R /F11 1209 0 R /F13 1211 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 1212 0 R /Pat96 1213 0 R >>>> /Length 1006 /Filter /FlateDecode >> stream xڽWMo9qR -NdA↘B2]e6`FtHl,3EH>,EiMdW{ >!b"\,GuV{y}}+iVuT{Y*SñV/>ɓOXlζͳIey^ò[^5o7ھjzm'axd)Ќ6;G?FqLҜX}ZBsH%L ƿ@gkR1x?1N{^<\=E7mjy@n7q׾| vT1KX+r6nA s 9q=4 %82{_CF  1ǻ4" 22% 8 Pf>umu2n,hkHkQ(g(4%8v˾ Śix$dUv1!ǘ:{SCքrqdyMY'_C֤WRrvO ۣ.s rT>{\fL,Ӎ73ˉd-J5D$s]YF;gG^ـ*:[ЬB36f xIň! zVНP$ʃSt80ڮl (hGU< xW8[8Ӫ15 W2 [>VׯulG!V u vW}E?ĩ2츿.֜K1-e"?,Nt{Vf.L%vjwyDBmn?dA}K{GĺymBӨSFpg#O!+S^rrW=4<׏/b2hk.wc1'kC|H8Y vT nc =^&h~Y+Lk=۾ |.QLR5|- endstream endobj 1205 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130208173232) /ModDate (D:20130211170244) >> endobj 1207 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 121 /Widths [ 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 1206 0 R >> endobj 1209 0 obj << /Type /Font /Subtype /Type1 /FirstChar 59 /LastChar 68 /Widths [ 277.8 777.8 500 777.8 500 530.9 750 758.5 714.7 827.9] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 1208 0 R >> endobj 1211 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 48 /Widths [ 329.4] /FontDescriptor 1014 0 R /BaseFont 1019 0 R /Encoding 1210 0 R >> endobj 1212 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1213 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1210 0 obj << /Type /Encoding /Differences [48/prime] >> endobj 1208 0 obj << /Type /Encoding /Differences [59/comma 65/A/B/C/D] >> endobj 1206 0 obj << /Type /Encoding /Differences [48/zero 98/b/c/d/e/f 105/i 108/l/m/n/o/p 114/r/s/t/u 121/y] >> endobj 1181 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation36) >> >> endobj 1182 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1183 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation38) >> >> endobj 1184 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation36) >> >> endobj 1185 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation37) >> >> endobj 1186 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation37) >> >> endobj 1187 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation38) >> >> endobj 1188 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1189 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1190 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1191 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1192 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1193 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1194 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1195 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1196 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1197 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1198 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1199 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1200 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1179 0 obj << /D [1202 0 R /XYZ 28.346 0 null] >> endobj 1201 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im28 1180 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1238 0 obj << /Length 879 /Filter /FlateDecode >> stream xWKs6W> \4=L=DWQeM44с |~4#M }FAzmtFthxLSwŋ8kudZm)DXVqqZZ5ۼ[nq0^YzXWoV/П:\z|锎߮Lh͘mqZ æk jU2zA k|(ʈ:6 NollU릀V`h;=".h0yXeӒ%NV'uvAy[TwH=!k%p)8/s:^:]EDת upN%L]aW;KP?]3+h'}G ɖ~nٖ[C^^U>&aVƥAr;oG-v|Uً"rZ[*>d(agt[ݠ/i>cAҁ=)Ӂkz_d6==t>ŖX8?}M ;}Fg?K.-g|fvV!jKb|N$;#ESmySV4*ŧR_&|ߩ* endstream endobj 1237 0 obj << /Type /Page /Contents 1238 0 R /Resources 1236 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1204 0 R /Annots [ 1216 0 R 1217 0 R 1218 0 R 1219 0 R 1220 0 R 1221 0 R 1222 0 R 1223 0 R 1224 0 R 1225 0 R 1226 0 R 1227 0 R 1228 0 R 1229 0 R 1230 0 R 1231 0 R 1232 0 R 1233 0 R 1234 0 R 1235 0 R ] >> endobj 1215 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/gauss2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 1239 0 R /BBox [187.253 427.496 352.323 497.797] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 1241 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 1242 0 R /Pat96 1243 0 R >>>> /Length 468 /Filter /FlateDecode >> stream xڵj1 ~ -BTKeyh م]4me"!ׯ<gsJEf~K?_$7@=GNdߚIfT N/ g"08V2g j. "sX2;)vf2gӾv"vfT9O;aC>Y7jp1gŘ/M;;˰u>~ W!opq&㰋'EzlS&YpSNS^uMmu1/yxK'kL`L-ڔ9/@ endstream endobj 1239 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130208173232) /ModDate (D:20130211171300) >> endobj 1241 0 obj << /Type /Font /Subtype /Type1 /FirstChar 49 /LastChar 116 /Widths [ 500 500 500 500 500 500 500 500 500 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 1240 0 R >> endobj 1242 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1243 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 1240 0 obj << /Type /Encoding /Differences [49/one/two/three 97/a 100/d/e 104/h 114/r 116/t] >> endobj 1216 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation37) >> >> endobj 1217 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1218 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation39) >> >> endobj 1219 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation37) >> >> endobj 1220 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation38) >> >> endobj 1221 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation38) >> >> endobj 1222 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation39) >> >> endobj 1223 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1224 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1225 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1226 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1227 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1228 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1229 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1230 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1231 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1232 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1233 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1234 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1235 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1214 0 obj << /D [1237 0 R /XYZ 28.346 0 null] >> endobj 1236 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Im29 1215 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1267 0 obj << /Length 982 /Filter /FlateDecode >> stream xWKs7 W;S!߼fɌR]˶&li;_+rײ$InFe|'mAy k^x3"l@ lwk57Cu5o[MIa}uov7IͶ6(=ߊXFߓi_.?$a2ۈ*t~xJ/Pfm2hM7p)yy^,%EMzL엮U`e$4FJƫf=?w~X#Ƣ1%OU",{`Ϩݽ%5GJsӸ:JžG`d"b]zbpK6dY&~tحFoԹ=K<*EKv.vexlt?J:"C&vKamǣsx!D.H*}?#>}nsԽ(1$p_KJic&;XU6z%1eYU+'F2L_2 endstream endobj 1266 0 obj << /Type /Page /Contents 1267 0 R /Resources 1265 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1204 0 R /Annots [ 1245 0 R 1246 0 R 1247 0 R 1248 0 R 1249 0 R 1250 0 R 1251 0 R 1252 0 R 1253 0 R 1254 0 R 1255 0 R 1256 0 R 1257 0 R 1258 0 R 1259 0 R 1260 0 R 1261 0 R 1262 0 R 1263 0 R 1264 0 R ] >> endobj 1245 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation38) >> >> endobj 1246 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1247 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation40) >> >> endobj 1248 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation38) >> >> endobj 1249 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation39) >> >> endobj 1250 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation39) >> >> endobj 1251 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation40) >> >> endobj 1252 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1253 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1254 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1255 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1256 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1257 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1258 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1259 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1260 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1261 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1262 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1263 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1264 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1244 0 obj << /D [1266 0 R /XYZ 28.346 0 null] >> endobj 1265 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1291 0 obj << /Length 712 /Filter /FlateDecode >> stream xWSS1c{hƣ22O@FZɣȈI~6y @Do-r{ň"DXpdVI')w`ؠ+|~8YoW糹 ql(W%wp}?_>/&oHN)"6ݒSC(~?98 E倉7<~i"d@g|o!)ÔH۲La)C6]&<SVYd#6&ً~룻pt?ϐK),)# 6Vyn-#\Ġl 3#G1;ݯܪX~)u+JѦ%ZT!C[| #.]/:0"t)Qo@d]f^FYAOPQa kSGė8*=(_UyKR!!_ݠnh{FQmab1K6O.GϠκX/ks> /Parent 1204 0 R /Annots [ 1269 0 R 1270 0 R 1271 0 R 1272 0 R 1273 0 R 1274 0 R 1275 0 R 1276 0 R 1277 0 R 1278 0 R 1279 0 R 1280 0 R 1281 0 R 1282 0 R 1283 0 R 1284 0 R 1285 0 R 1286 0 R 1287 0 R 1288 0 R ] >> endobj 1269 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation39) >> >> endobj 1270 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1271 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation41) >> >> endobj 1272 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation39) >> >> endobj 1273 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation40) >> >> endobj 1274 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation40) >> >> endobj 1275 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation41) >> >> endobj 1276 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1277 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1278 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1279 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1280 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1281 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1282 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1283 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1284 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1285 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1286 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1287 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1288 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1268 0 obj << /D [1290 0 R /XYZ 28.346 0 null] >> endobj 1289 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im27 1052 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1315 0 obj << /Length 1199 /Filter /FlateDecode >> stream xXKo#7 Whz^ ,۸nޱl /iɾ^"CR"8(LpJZ%B;^[jR9qwb6+2Ѳ5#G IFKIavüִLi"ʁK. Vڄʂ;Lf̑m{]a8#tTb.uZ:: )$~Q<rXγXEҪTv]V4LJX*%FP^R^DsT׫} |%5ezL|CO[QC]"'MI_/xƒWA 5PV;_ ÔxJUŇSyvTD] $/z9X>!%+h0ê2%HjHU܉fB,Enmv"sTp5. L0kjO+niR /9h=OD9^6v]F|F>?˖FYFWz{\l79C N]P Z, CY~j >&̟[˝(8Q|SQS4+䆏br_I*7E<(Ա~iоZ(bg1yR<GtGBG $9ͺ;׭H<ql;FM /j^\IwBO哶RHt)ew0%B_fK$̭%= kDX='6踲WvaoLIw ϙdoR:'i">1~<B$?G9J/R]|F*YxCݨQtIX'a9"34|sÿeh)iH9]d 5MH&H 3eJ#YOo yz,B&SȲHqxmH6K']Im7o<ţ:ړed8)M5\hq!VUK 3'< endstream endobj 1314 0 obj << /Type /Page /Contents 1315 0 R /Resources 1313 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1204 0 R /Annots [ 1293 0 R 1294 0 R 1295 0 R 1296 0 R 1297 0 R 1298 0 R 1299 0 R 1300 0 R 1301 0 R 1302 0 R 1303 0 R 1304 0 R 1305 0 R 1306 0 R 1307 0 R 1308 0 R 1309 0 R 1310 0 R 1311 0 R 1312 0 R ] >> endobj 1293 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation40) >> >> endobj 1294 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1295 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation42) >> >> endobj 1296 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation40) >> >> endobj 1297 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation41) >> >> endobj 1298 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation42) >> >> endobj 1299 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1300 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1301 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1302 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1303 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1304 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1305 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1306 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1307 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1308 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1309 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1310 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1311 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1312 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1292 0 obj << /D [1314 0 R /XYZ 28.346 0 null] >> endobj 1313 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F21 79 0 R /F45 164 0 R /F24 1317 0 R /F39 78 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1342 0 obj << /Length 1196 /Filter /FlateDecode >> stream xXKo7W(d^ @jdK$; 3%w_:@/&9;3ř@vU*iL) U+ʉ˕8%_!`b~*` ʊR9|Vi9]^o3Z/iֻa#enhA:%*Ujuuh!\Š!9ju H2r]\J K\c.浦eZN V]jpI&\EUa2cl% C>BG%)oxqRӯP⩌N%Ks>_K8y+G8<+~Yċ LeeE٩>q|*%(b^"h/8Kd =*J|ڗWRSV[McbM=qlE u=4%}~o' p]]7kzT֋C1n:NGTUX|* T#\r`SN<ݣRH_'-A$uWC"N4 =Rf'2G5WwT E y'b?=i^frzM-l_v-m~S%g ,v\#/Ԕcjsme^mglit=쮷v,=T%Q0rP qH_>̯A˝S-8QxS'Qk5 =br_IzoxP.1Ԡ}PD/O'bxjQ3 !hbޑ&nEIE (k/G݇)r -=9kciJ".SE#L[J$;ypCr!suɷI2stIO 1/"aĖT$:Dz.M)Ic69MJ$M$>^4Ə' Oýq!dH/SH{@$^琦;jT]`D -8Ieg;8 /"4fJ*tN4BCF#jM;ҹ(%L*n҈uӛwB~'Y@/cE+dާ7BEkpkC]:JƵrҷaDk?+Gu'2) pRޛ$k):/J \rhoq<E endstream endobj 1341 0 obj << /Type /Page /Contents 1342 0 R /Resources 1340 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1204 0 R /Annots [ 1320 0 R 1321 0 R 1322 0 R 1323 0 R 1324 0 R 1325 0 R 1326 0 R 1327 0 R 1328 0 R 1329 0 R 1330 0 R 1331 0 R 1332 0 R 1333 0 R 1334 0 R 1335 0 R 1336 0 R 1337 0 R 1338 0 R 1339 0 R ] >> endobj 1320 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation41) >> >> endobj 1321 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1322 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1323 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation40) >> >> endobj 1324 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation41) >> >> endobj 1325 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation42) >> >> endobj 1326 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1327 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1328 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1329 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1330 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1331 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1332 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1333 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1334 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1335 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1336 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1337 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1338 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1339 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1318 0 obj << /D [1341 0 R /XYZ 28.346 0 null] >> endobj 1340 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F21 79 0 R /F45 164 0 R /F24 1317 0 R /F39 78 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1365 0 obj << /Length 1244 /Filter /FlateDecode >> stream xXKo7WB v%Ӟ6A@j==$9e!܇hǎ4<rFq.@dEZD^[Z%Q9qgGBO]_ξy^ J:Bڶby*h~Y56ׇrЮmno67/ Cf~kh65+Z9Z!+nheђvbZ '+?oWG^jm'&ͷ!:$dPHtĢ8RAg_;- ZZZӞHbᤳ.d1s6Fn|dUvn*RjJA3 JcZT!sqN0[PH*+p$QQBJQUX|eMn8,Ԃ5R} A< R5p[t)\=vdQlk6Aj=iιIy%LTn{K_2"AVU &ȆQ:F ;1:Av_4mǀKTZݽW.W7*5~"~GjU2Uju~O:Q4:sg i ^YǓ/ O? 8>sJLsj;wW(ЈD* ̜I4`XqzBe3N?׃48]kh[(y9Y J`@)mx)ͬ((zN7c => "p|!>g}](<|1ƵouM]:w{]*;z DO@zc)ᬼ [)):/J *\8 '0ƓI,?}Xm} endstream endobj 1364 0 obj << /Type /Page /Contents 1365 0 R /Resources 1363 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1366 0 R /Annots [ 1343 0 R 1344 0 R 1345 0 R 1346 0 R 1347 0 R 1348 0 R 1349 0 R 1350 0 R 1351 0 R 1352 0 R 1353 0 R 1354 0 R 1355 0 R 1356 0 R 1357 0 R 1358 0 R 1359 0 R 1360 0 R 1361 0 R 1362 0 R ] >> endobj 1343 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation42) >> >> endobj 1344 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1345 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation44) >> >> endobj 1346 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation42) >> >> endobj 1347 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1348 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1349 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation44) >> >> endobj 1350 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1351 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1352 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1353 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1354 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1355 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1356 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1357 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1358 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1359 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1360 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1361 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1362 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1319 0 obj << /D [1364 0 R /XYZ 28.346 0 null] >> endobj 1363 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F24 1317 0 R /F45 164 0 R /F36 1316 0 R /F40 605 0 R /F39 78 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1390 0 obj << /Length 1040 /Filter /FlateDecode >> stream xXK6W(3CR|rH׷UVm}Him4i^y$^` 8F=!ʚ #8 [/ޜ)=uqx-Ć4 \_M)8nSVRñ;>/+e]z{g(}"k}D_ȟ\+]}-+a}0"eї4+)V $8cگڟaPvaɽ́Upp)]Ya|.r5VB v1u{j a揸zfj7ДXkƐ%"{ ˥5n k㦟ejP&3'1r ֊| ~痚P+Uw*w1*"u 2I9EΤ䪞RVM )fXǁ h_xN鑶\?Kp\&0Mbi;Y튷6fmRir?Yy{}c-;c'/}t-Y%9ow-ٌQ5c^riҪqI:8$PyoUlTBё=)Yְ%KyaIFFIQm@p1+ A2Nsg\ %HшOB$Ct'9)xufkEmR=I>Ԋnp,cr2B_a) Svh`|j!d|w0o2:w,Ԋ .&mW_OEV)oO-۩k}&IZEQ9 'Hrg* k߸+-‚uFҫ"YHf Ԛ)|yHH38KeΘUϘ'`1Y`ᄀ2'یPf86ӱ%].l% g ^dذ@=ݔw:L1EɓYR> /Parent 1366 0 R /Annots [ 1368 0 R 1369 0 R 1370 0 R 1371 0 R 1372 0 R 1373 0 R 1374 0 R 1375 0 R 1376 0 R 1377 0 R 1378 0 R 1379 0 R 1380 0 R 1381 0 R 1382 0 R 1383 0 R 1384 0 R 1385 0 R 1386 0 R 1387 0 R ] >> endobj 1368 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1369 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1370 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation45) >> >> endobj 1371 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1372 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation44) >> >> endobj 1373 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1374 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1375 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1376 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1377 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1378 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1379 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1380 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1381 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1382 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1383 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1384 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1385 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1386 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1387 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1367 0 obj << /D [1389 0 R /XYZ 28.346 0 null] >> endobj 1388 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1416 0 obj << /Length 1043 /Filter /FlateDecode >> stream xXKo8W(;CR|.-Pn|k{Pe1۩6;$EJb/q 5rchEZZp++&(4۷l5{yhw-Vh@HUŒ*^sžy))>Óy+^?ˈ.}|҇6ۦEdf鱿R--Ňy)l F,9nDUTqYev!>Vv߫nnVJa8Uf^bd*rbHԂzBBmf |g!^Oî]]msI.݃LX.EWrN*]7~l6,K#S&:(G&+!5Gc~Sl[ozTz>UF~!G1*n"u 2I)ꬍrIl]z~T™@B>O}k_5n7YzḨIXQs&ݹq _N5YMe{|?'+w*??ֲ;v,GђѴvgDM%H:[U,zN3Le6TcABlkY?Nn!S%=90+d$h;Bp: X1v?s +H&|5q;#H3R E+R> \{QLAoc\C(Q$ I+zN@#RaM;sgVsS8bT0L7;IH}lo 6Ë_ٺYVs/Yo%v>@$YEiP9 'HrTs_ʎ+#‚UFWEIP-hrBM"!9d$]f;Czs61_0g_d2 Ha :Od+Y8M"/ aMy_4!e(œS/; EmyH8,Dl$I,_$6 endstream endobj 1415 0 obj << /Type /Page /Contents 1416 0 R /Resources 1414 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1366 0 R /Annots [ 1394 0 R 1395 0 R 1396 0 R 1397 0 R 1398 0 R 1399 0 R 1400 0 R 1401 0 R 1402 0 R 1403 0 R 1404 0 R 1405 0 R 1406 0 R 1407 0 R 1408 0 R 1409 0 R 1410 0 R 1411 0 R 1412 0 R 1413 0 R ] >> endobj 1394 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation44) >> >> endobj 1395 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1396 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1397 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1398 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation44) >> >> endobj 1399 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1400 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1401 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1402 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1403 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1404 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1405 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1406 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1407 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1408 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1409 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1410 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1411 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1412 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1413 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1391 0 obj << /D [1415 0 R /XYZ 28.346 0 null] >> endobj 1414 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1439 0 obj << /Length 1041 /Filter /FlateDecode >> stream xXK6W(#3CR|rH׷UVi}HimI6馗q'^`W38F!ʊ #8 -[ޞ(}|1{-CŊ́ 4 Xߋ7\bz^Jml^*72v{h觶vxM^ זZh)nN0.@b%@^jnnZ{OnEKN\o%Ϧ< )QZuUhYE7uwG(`YW0kk{zkzŶ$m ^,| KEke +@6%^) # ͕ܐ1~ӧܗnoR}6@xV(R'))R~"@Vg9*ʖKg*%W×#y7q K5w7qQc)GMQoK4i_dꤷou(M\ c- 1k=;B~{)ndttz6;gIg+vüBSҪqI: u !_lkY?NEn!)Np]SbK2W4JB<zh#$4Vݟm$ '_8͝SI3ܒ E#R< \J( 2ձY!(JoI!WtbO@c5/*,Hph#|jw PlJ"n CϤx(Nb"1 6ŋGP/ٺd\K?eI5Y߯ӭ &j Zʁv^8Ac.*1*K8qe7}*d endstream endobj 1438 0 obj << /Type /Page /Contents 1439 0 R /Resources 1437 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1366 0 R /Annots [ 1417 0 R 1418 0 R 1419 0 R 1420 0 R 1421 0 R 1422 0 R 1423 0 R 1424 0 R 1425 0 R 1426 0 R 1427 0 R 1428 0 R 1429 0 R 1430 0 R 1431 0 R 1432 0 R 1433 0 R 1434 0 R 1435 0 R 1436 0 R ] >> endobj 1417 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation45) >> >> endobj 1418 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1419 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1420 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation43) >> >> endobj 1421 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation44) >> >> endobj 1422 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1423 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1424 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1425 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1426 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1427 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1428 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1429 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1430 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1431 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1432 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1433 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1434 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1435 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1436 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1392 0 obj << /D [1438 0 R /XYZ 28.346 0 null] >> endobj 1437 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1463 0 obj << /Length 1103 /Filter /FlateDecode >> stream xXKs6WV@ǵtzp29(s"JD%m}dɶ4q&=X[6nhVբW7umF .ITӒT]}.9{ +HUe,ny7OmUϯ>#u|l/ fr9^$+=d"L6i 4{]KR*a&o/M\BAuq.?{i=l`#BmLh#.A$=tH0qT8z-:YJWdr"W)=I8DQHԊ)HDnu$J8;q%|dJcøf\PocY D"-|P"w̉c"X4 Y0Q"EIE +xPN0"+p-0<F>!*#QEӆpH6T0 NG'0{ Kh,Q`}_)% Wxk~$l 032$u… gQqX8|U"UWdAp5y 8r(a;T&һ_a4e{C 2*K (ѱ.ö[Ʒ4B{panc$7q|`X,0l!%n MqxYqVYq I,[06 endstream endobj 1462 0 obj << /Type /Page /Contents 1463 0 R /Resources 1461 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1366 0 R /Annots [ 1441 0 R 1442 0 R 1443 0 R 1444 0 R 1445 0 R 1446 0 R 1447 0 R 1448 0 R 1449 0 R 1450 0 R 1451 0 R 1452 0 R 1453 0 R 1454 0 R 1455 0 R 1456 0 R 1457 0 R 1458 0 R 1459 0 R 1460 0 R ] >> endobj 1440 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 5.139 5.139] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 1464 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 1464 0 obj << /Shading << /Sh << /ShadingType 3 /ColorSpace /DeviceRGB /Domain [0.0 2.5697] /Coords [1.67305 3.6656 0.0 2.5697 2.5697 2.5697] /Function << /FunctionType 3 /Domain [0.0 2.5697] /Functions [ << /FunctionType 2 /Domain [0.0 2.5697] /C0 [0.88 0.88 0.955] /C1 [0.4 0.4 0.775] /N 1 >> << /FunctionType 2 /Domain [0.0 2.5697] /C0 [0.4 0.4 0.775] /C1 [0.14 0.14 0.49] /N 1 >> << /FunctionType 2 /Domain [0.0 2.5697] /C0 [0.14 0.14 0.49] /C1 [0.09999 0.09999 0.34999] /N 1 >> << /FunctionType 2 /Domain [0.0 2.5697] /C0 [0.09999 0.09999 0.34999] /C1 [1 1 1] /N 1 >> ] /Bounds [ 0.797 1.59401 2.1918] /Encode [0 1 0 1 0 1 0 1] >> /Extend [true false] >> >> /ProcSet [ /PDF ] >> endobj 1441 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1442 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1443 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation48) >> >> endobj 1444 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1445 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1446 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation50) >> >> endobj 1447 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation51) >> >> endobj 1448 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1449 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1450 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1451 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1452 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1453 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1454 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1455 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1456 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1457 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1458 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1459 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1460 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1393 0 obj << /D [1462 0 R /XYZ 28.346 0 null] >> endobj 1461 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R /Im29 1215 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1490 0 obj << /Length 1106 /Filter /FlateDecode >> stream xXr7+p@rM%Qũd'WpdMCNipؑJ"Fw2b-abZ-=HFP'5VP. 4frydtn#Q<'7sKJS&^oզә4je5~޷kg-_^L~8 q"=Ֆ55ґ:C~\H1l!kF\IbSMb:ńI~}HYm^QIVۻTjm|:u~@NBVY??ES7 _4şf[Z얻m$$#KtomTýָG^Q~].ah?vt~jWa׷l$Y&w{qOK`BBus1ͱ?UޖTU[]V]B8 \z=Njdp4L r&MS;xhIfJXK'|*ˢK(hp=~KϞe9M l$Tߓɑ69D]G'p2*P+yE&)2xbۓLTAxHDvIPGR  ax؀|FE_7%7λP ,VC-'0{ ⁥Ifq+,I`}[̔oO߫m5x?@]c|EAEr|:B̌3B@r(xz,SRg *q:K_2x@q 9 0Q*5~JzW RX HSxg;!sY2r5z6z8uEʅ^yrSaInuAY,0lAHA}<`CVbUD\ce6cCC endstream endobj 1489 0 obj << /Type /Page /Contents 1490 0 R /Resources 1488 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1366 0 R /Annots [ 1468 0 R 1469 0 R 1470 0 R 1471 0 R 1472 0 R 1473 0 R 1474 0 R 1475 0 R 1476 0 R 1477 0 R 1478 0 R 1479 0 R 1480 0 R 1481 0 R 1482 0 R 1483 0 R 1484 0 R 1485 0 R 1486 0 R 1487 0 R ] >> endobj 1468 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1469 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1470 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation49) >> >> endobj 1471 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1472 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1473 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation50) >> >> endobj 1474 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation51) >> >> endobj 1475 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1476 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1477 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1478 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1479 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1480 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1481 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1482 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1483 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1484 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1485 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1486 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1487 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1465 0 obj << /D [1489 0 R /XYZ 28.346 0 null] >> endobj 1488 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R /Im29 1215 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1514 0 obj << /Length 1101 /Filter /FlateDecode >> stream xXr7+p@rM%Qũd)'WpdMCNipER9X4z}Ќ#Ma0~ #& ʅ!\MΏ;p9gg3RAҔ G.M|*yt&ftͪz5q pYyGg.2NBmHODpMt ΐ'JL)qʚQnt4Wҧ/TjӤܨlB̤TUR6Qv$|*l6IwZ u~DN:Bm=ٛNggnwE]4mC G2PR^a[gݑ1g:㫐9BY!OFA$ yiLt+QZfmFxLPM |6GcQUVU[]ᆛ7Y:p3+pu:?KF W{LSDH*'m(i }so -L K7O~^41Q;g3 sٓ. $ 29&'\HzQ?`0p[}B2z%<^/F$nn&8> /Parent 1515 0 R /Annots [ 1492 0 R 1493 0 R 1494 0 R 1495 0 R 1496 0 R 1497 0 R 1498 0 R 1499 0 R 1500 0 R 1501 0 R 1502 0 R 1503 0 R 1504 0 R 1505 0 R 1506 0 R 1507 0 R 1508 0 R 1509 0 R 1510 0 R 1511 0 R ] >> endobj 1492 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation48) >> >> endobj 1493 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1494 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation50) >> >> endobj 1495 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1496 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1497 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation50) >> >> endobj 1498 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation51) >> >> endobj 1499 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1500 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1501 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1502 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1503 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1504 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1505 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1506 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1507 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1508 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1509 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1510 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1511 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1491 0 obj << /D [1513 0 R /XYZ 28.346 0 null] >> endobj 1512 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R /Im29 1215 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1538 0 obj << /Length 1097 /Filter /FlateDecode >> stream xXKs6WV ǵtzp2=(s"JD%m}~5mjgz,yGaFIM C \=un>Gg3pn Biʄ#%ySJ^mźf7Ic]5]}YO:jҟ%wd|}1aqbDz-'kj#u^u|9brٌ]֌r>|oU&Fuߋ y3RUBFO "vv$z9Lq{r@Ϧ74lֻH&I8*(%܆$Odو>;y^,ΩX~r~6 nWLYE,yk UjK{JP%WP6Sk? x!.pOy_v3LEmOpkhHM3۵b!]J&Z>OE&g`6PoCU~շvMiy;pA3`Wk%+Nd" N6qiBKEK2SRM솟:S;\N4`T{qt}q.PZH"P? 79HýG)2*AP+ |E&A)2x|;LPAAxHEqEGR  < EH#Ad &:rf@C!vv.i:pI!H*-{ % |X9jX(qwH|H<04BA>dV>+6d>gI;%7ʻP ,VC-vPe&Jy }RQzY!/MֿWxk~Ɓ, 0H33$… 93)rᘒ:SUpFLIW(u@JvURw~EJ4e{!̄sD,Rt˅{< F]ḷ| ;DsrS$7qɣ]nchd|J\|K8|fy^ endstream endobj 1537 0 obj << /Type /Page /Contents 1538 0 R /Resources 1536 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1515 0 R /Annots [ 1516 0 R 1517 0 R 1518 0 R 1519 0 R 1520 0 R 1521 0 R 1522 0 R 1523 0 R 1524 0 R 1525 0 R 1526 0 R 1527 0 R 1528 0 R 1529 0 R 1530 0 R 1531 0 R 1532 0 R 1533 0 R 1534 0 R 1535 0 R ] >> endobj 1516 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation49) >> >> endobj 1517 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1518 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation51) >> >> endobj 1519 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation46) >> >> endobj 1520 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation47) >> >> endobj 1521 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation50) >> >> endobj 1522 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation51) >> >> endobj 1523 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1524 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1525 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1526 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1527 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1528 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1529 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1530 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1531 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1532 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1533 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1534 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1535 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1466 0 obj << /D [1537 0 R /XYZ 28.346 0 null] >> endobj 1536 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R /Im29 1215 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1562 0 obj << /Length 1240 /Filter /FlateDecode >> stream xXKs6WV cn3iɡ큡iHƔ.lq6nNϞK+Z!Ï1A:pT󜀠 ) Ya'3:$'b(זYAɅ )s8uRFe,$e+4Qx7$pH"_x L#T0qZϙC0MS BgsԠIGp"EP>ϑШ2'P|w NP#c(F## laFs3OF137n70=J'v&jqQ Qτ? ko|ٌ3O?̈}~D^hwLY4#IPPjG.dh16i^"I%^)8FD1 ILVFɋHInFwB):;G_\~e)ˈ/]=2Q02OQ~cM+j]e:y_\kwyJ6LSv!h,?I::!AxGJ3Iƃ2EŧQ%.bP+zGIյ}=,^7@^vxÈڄYK w aqGD6s1Z3WXyt/ʽ2m0)nSW/Lr hqe Όs8ZK~\ g?.WΪMhۢ|ww2̻yXة n8ʩAM9v1.@O5_ź3Z!ӭ>vs-znL#J BG߽.53yY]~BݶQTB쯞um Dt^,(;+) 3sCIYHެ ]l]|} ˮnbfQy߷;5´ t6_u]zTk~_|,+ Wݾ^K*[j %vXos* p{9(n ;J0yp}#?G}0i c@]B6OhTWfW'KXֽm>m TDW% endstream endobj 1561 0 obj << /Type /Page /Contents 1562 0 R /Resources 1560 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1515 0 R /Annots [ 1539 0 R 1540 0 R 1541 0 R 1542 0 R 1543 0 R 1544 0 R 1545 0 R 1546 0 R 1547 0 R 1548 0 R 1549 0 R 1550 0 R 1551 0 R 1552 0 R 1553 0 R 1554 0 R 1555 0 R 1556 0 R 1557 0 R 1558 0 R 1559 0 R ] >> endobj 1539 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation50) >> >> endobj 1540 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 1541 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation52) >> >> endobj 1542 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation50) >> >> endobj 1543 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation51) >> >> endobj 1544 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation51) >> >> endobj 1545 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation52) >> >> endobj 1546 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1547 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1548 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1549 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1550 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1551 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1552 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1553 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1554 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 1555 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 1556 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 1557 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 1558 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 1559 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation1) >> >> endobj 1467 0 obj << /D [1561 0 R /XYZ 334.488 0 null] >> endobj 1563 0 obj << /D [1561 0 R /XYZ 334.488 0 null] >> endobj 1560 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm1 12 0 R /Fm5 53 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1587 0 obj << /Length 723 /Filter /FlateDecode >> stream xWKO1 ϯq94LJR q@SbAlڙu2,RJa۱?',9 u!%ekFkXYwâ{K ML8 A2,Npexlu΅8y>.8Kɓ&Za!>.bgM_`lKq6sPosY\)|V?Fl^d]^㻋ˡ$K:LH~s@IZrVg/BDe3⒌ \(s`وϡ;a KzNysbmAlW6,#qSFQcnSw],+{"R;n#-)&(_\˜*)lu)|)jhkFՠz<ݧQDmpTo,W'۾YokqpKMd~޷$P=6 UƐX!`dpRWH]_Uhu"7JT#є{NTP}Y(RJi͙}h{LķDE(;l]*"/A"ہ)8=5FC=mퟎ[nueJ E2/ROUd|&[IŶ!CScl~y'KUvZUi!i$d, G~ endstream endobj 1586 0 obj << /Type /Page /Contents 1587 0 R /Resources 1585 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1515 0 R /Annots [ 1565 0 R 1566 0 R 1567 0 R 1568 0 R 1569 0 R 1570 0 R 1571 0 R 1572 0 R 1573 0 R 1574 0 R 1575 0 R 1576 0 R 1577 0 R 1578 0 R 1579 0 R 1580 0 R 1581 0 R 1582 0 R 1583 0 R 1584 0 R ] >> endobj 1565 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation51) >> >> endobj 1566 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1567 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation53) >> >> endobj 1568 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation51) >> >> endobj 1569 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation52) >> >> endobj 1570 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation52) >> >> endobj 1571 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation53) >> >> endobj 1572 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1573 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1574 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1575 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1576 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1577 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1578 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1579 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1580 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1581 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1582 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1583 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1584 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1564 0 obj << /D [1586 0 R /XYZ 28.346 0 null] >> endobj 1585 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1611 0 obj << /Length 900 /Filter /FlateDecode >> stream xWMS0WJ>)r`d'Bi}W%J)-K}]}+Y9~{#҈4^Lj,0l۰ɝǎo7GhwMϙ-\+Ŧ3.x")EuȢħf5b࿹EHLGT/ \*P;^X pqǺec2'{>p)6.<8T$zȝ|(,^ŷf#"g@]_vqf<ۋU6.DzyTMq϶G'(lw68 zn]j]ͣ+9'Lq37cb*zxYQCkQդ,PP3 s/l1mɵeݏl;g{~ۢShI: :!蒍Y Ζ˅]N@&FJ& oS6:QVǩHB(T-W9ZK>GhaC&a`t[H)7X8Mo|pH4-Q)I#QhQoβ\ChQn$ QƴH=CGS: th\tgU%K]))ywToJ:_'eao Nh/}-^xlSw{;~@$_s_T Kp(L[-dפ%ˌ!i:#Hi@a@W+hZ#ufL3SJ9O_)}3TrY`ᄀ2?Rpǚb o+e?uE_/lE =ݔ_u01&ԓ~ %>9:Nx/cC1W%Ue/bLayOZ? endstream endobj 1610 0 obj << /Type /Page /Contents 1611 0 R /Resources 1609 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1515 0 R /Annots [ 1589 0 R 1590 0 R 1591 0 R 1592 0 R 1593 0 R 1594 0 R 1595 0 R 1596 0 R 1597 0 R 1598 0 R 1599 0 R 1600 0 R 1601 0 R 1602 0 R 1603 0 R 1604 0 R 1605 0 R 1606 0 R 1607 0 R 1608 0 R ] >> endobj 1589 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation52) >> >> endobj 1590 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1591 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation54) >> >> endobj 1592 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation52) >> >> endobj 1593 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation53) >> >> endobj 1594 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation55) >> >> endobj 1595 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1596 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1597 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1598 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1599 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1600 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1601 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1602 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1603 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1604 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1605 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1606 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1607 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1608 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1588 0 obj << /D [1610 0 R /XYZ 28.346 0 null] >> endobj 1609 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F61 1612 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1638 0 obj << /Length 1041 /Filter /FlateDecode >> stream xWK6 WVyf c:M[ATKd}R^i6\L#>dvL q1[DSFrr& Avvѧ??܀e zlΥ Fkް߲J"߿0",!? 뗋kLR&-W008V"B慛O% _]6چYd_䂃ɑpWt\J)7M݀ 0?i- UPhObSGe4vGr}q7aߎ^/ӝo \UjP9]O"{4 v&LmkKJpo-@uԛk1{J}Ȓw7Ski._sN(reuz)gsी+0ŕ-b@t)߲+?Nr$4\Np휳EO46,vQ!śG`f憁 y@taHׅ3xq*GkE+E!#`>Q\h AIddEA@'ZA~ ReA& ktX~N]Q琕+]); ӞF|8Ͻ8ya1Z xZIu۾b}[ ɖ~n_x_!,Q*'#)pjfFG+Z _Cc*!&##UbD3xJϔ-V%5(‚g'D:i^%3H+ubJG_ٮ/S`^tvDž瓄)X"d GSJP&yQVrU҂y"6I8,Ob endstream endobj 1637 0 obj << /Type /Page /Contents 1638 0 R /Resources 1636 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1515 0 R /Annots [ 1616 0 R 1617 0 R 1618 0 R 1619 0 R 1620 0 R 1621 0 R 1622 0 R 1623 0 R 1624 0 R 1625 0 R 1626 0 R 1627 0 R 1628 0 R 1629 0 R 1630 0 R 1631 0 R 1632 0 R 1633 0 R 1634 0 R 1635 0 R ] >> endobj 1616 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation53) >> >> endobj 1617 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1618 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation55) >> >> endobj 1619 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation52) >> >> endobj 1620 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation53) >> >> endobj 1621 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation55) >> >> endobj 1622 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1623 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1624 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1625 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1626 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1627 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1628 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1629 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1630 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1631 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1632 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1633 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1634 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1635 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1613 0 obj << /D [1637 0 R /XYZ 28.346 0 null] >> endobj 1636 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F61 1612 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1661 0 obj << /Length 951 /Filter /FlateDecode >> stream xWˎ: +tF%֪@N]N.uc͸KIɤtG$ER{iDLLXQvhvѷ׋gi.b 7J֗zV74= #rYol_-$7$L-]?[E6+PX瀳)%AwBES|> /Parent 1662 0 R /Annots [ 1639 0 R 1640 0 R 1641 0 R 1642 0 R 1643 0 R 1644 0 R 1645 0 R 1646 0 R 1647 0 R 1648 0 R 1649 0 R 1650 0 R 1651 0 R 1652 0 R 1653 0 R 1654 0 R 1655 0 R 1656 0 R 1657 0 R 1658 0 R ] >> endobj 1639 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation54) >> >> endobj 1640 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1641 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1642 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation52) >> >> endobj 1643 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation53) >> >> endobj 1644 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation55) >> >> endobj 1645 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1646 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1647 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1648 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1649 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1650 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1651 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1652 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1653 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1654 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1655 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1656 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1657 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1658 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1614 0 obj << /D [1660 0 R /XYZ 28.346 0 null] >> endobj 1659 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F61 1612 0 R /F39 78 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1685 0 obj << /Length 647 /Filter /FlateDecode >> stream xVKo1ﯘ3OHHP큀Fgƛi|;o#\ɀ{+J^156+8=t}| `!Xdl@!`>-~v1\~پx\Mjܬo?/O as{ǓkZ u_< ;p+C7 & m* q99LB8= /0K)Io:^#Li4m\p~W"5qєԎHK&s!+q=8cw#CŜvR6k&'W(H'5H1FJJR+o*)])|-n{FUz{s/"v8Tk/Ϡ}#^xҋlcw{[~$,Y7F(`,_0(Y/|5yd.2z B|eCO8QزP.2e[0ۧϘ4(T,B=!@g| :mV_alm?}l%$*RKӄAOքy/v}h/ΫjZ4/$OdܾL徫OT] endstream endobj 1684 0 obj << /Type /Page /Contents 1685 0 R /Resources 1683 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1662 0 R /Annots [ 1663 0 R 1664 0 R 1665 0 R 1666 0 R 1667 0 R 1668 0 R 1669 0 R 1670 0 R 1671 0 R 1672 0 R 1673 0 R 1674 0 R 1675 0 R 1676 0 R 1677 0 R 1678 0 R 1679 0 R 1680 0 R 1681 0 R 1682 0 R ] >> endobj 1663 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation55) >> >> endobj 1664 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1665 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation57) >> >> endobj 1666 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation55) >> >> endobj 1667 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1668 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1669 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation57) >> >> endobj 1670 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1671 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1672 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1673 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1674 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1675 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1676 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1677 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1678 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1679 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1680 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1681 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1682 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1615 0 obj << /D [1684 0 R /XYZ 28.346 0 null] >> endobj 1683 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1709 0 obj << /Length 927 /Filter /FlateDecode >> stream xWKo7WQ:ג-P Cj==(e4ɮ~w-A;%WB#k Ɓn5prs֋o()*/!:$jASհߖ߯ew?77Oeb(׷2s2jZi]ir,~%4btG޶%i|E-g~nn91cvo(7%0 6J Z*5q΄e 54@4mAzvR vAhfb=E a# 'C̖ͪ޶8P6A7E.S乽k̈́^(Dh&!fw@Zm< _yyB` Wpb\iw7Иdx G0!{H&mMhǚHtU hKvΎYdlSBt߀t<F8gG; (M Kn>k ]8Ǥ+ZS Y§ؐCB[!"gת ep*|Vʫa\3WNqO$qʤXm-]*28^cǶQMoi%NvW/x]'sㅝ^zͦH9.M|0S%aq>R4EAS}> /Parent 1662 0 R /Annots [ 1687 0 R 1688 0 R 1689 0 R 1690 0 R 1691 0 R 1692 0 R 1693 0 R 1694 0 R 1695 0 R 1696 0 R 1697 0 R 1698 0 R 1699 0 R 1700 0 R 1701 0 R 1702 0 R 1703 0 R 1704 0 R 1705 0 R 1706 0 R ] >> endobj 1687 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1688 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1689 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation58) >> >> endobj 1690 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1691 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation57) >> >> endobj 1692 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation59) >> >> endobj 1693 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1694 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1695 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1696 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1697 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1698 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1699 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1700 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1701 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1702 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1703 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1704 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1705 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1706 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1686 0 obj << /D [1708 0 R /XYZ 28.346 0 null] >> endobj 1707 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1735 0 obj << /Length 931 /Filter /FlateDecode >> stream xXKs7 W:ZN:Sgk&u^2wϷuV}W%0 m8'EG*UĜIy㋖"lUk4~NZ_Jlҭn3 B@XŃ:%baBFj/yjV5[7*e[Sg{Uu\ (V_E8,F$&Pw@Z+#rW,K3N CyyS>O#a-F޻D>l;Ӈ B2 J{^ <(Zf%BNSHVOٱ?8YCec6)!oAtr<FP*v2B#CQn6k ]8χ)w*ZS YϹyIz IdN)(EE{#ԓsMAK%}֟aT.|aB"CkUK8MZ Wðf$_q:w#|%,byh}b}_+˖~n-%z$*IY a̯E65'gLJ"5""K"T="w JgH=,B!ӆ"YF\ x6_xow׵27\El I>O`>Z!%Mc461eYU-'J1Lf>qO endstream endobj 1734 0 obj << /Type /Page /Contents 1735 0 R /Resources 1733 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1662 0 R /Annots [ 1713 0 R 1714 0 R 1715 0 R 1716 0 R 1717 0 R 1718 0 R 1719 0 R 1720 0 R 1721 0 R 1722 0 R 1723 0 R 1724 0 R 1725 0 R 1726 0 R 1727 0 R 1728 0 R 1729 0 R 1730 0 R 1731 0 R 1732 0 R ] >> endobj 1713 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation57) >> >> endobj 1714 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1715 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation59) >> >> endobj 1716 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1717 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation57) >> >> endobj 1718 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation59) >> >> endobj 1719 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1720 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1721 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1722 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1723 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1724 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1725 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1726 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1727 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1728 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1729 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1730 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1731 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1732 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1710 0 obj << /D [1734 0 R /XYZ 28.346 0 null] >> endobj 1733 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1758 0 obj << /Length 928 /Filter /FlateDecode >> stream xXKo7Wqu;ג)P Cj9=e4Ɏ~Mݼ\y~3||G#H{yO'PEsNUհ<ͳ鮶~u}yMo~- Y^fus1Z]?s֪4m"hmz^]c}ms pef_o.n΋n((~N&hUl1xc&/Rv*`Za$S䒦R蠌eon=tajǁ> T_<(S,F&*-aبZ%oCj~&c[Á:N}We^J -@FDJQ:T^WۿVçJcR?!ߟ&iy(}ibR,(DEz#+rS%B8/PQa1Fb-_|eUMJ8"70w3;K>,y Q> /Parent 1662 0 R /Annots [ 1736 0 R 1737 0 R 1738 0 R 1739 0 R 1740 0 R 1741 0 R 1742 0 R 1743 0 R 1744 0 R 1745 0 R 1746 0 R 1747 0 R 1748 0 R 1749 0 R 1750 0 R 1751 0 R 1752 0 R 1753 0 R 1754 0 R 1755 0 R ] >> endobj 1736 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation58) >> >> endobj 1737 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1738 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1739 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation56) >> >> endobj 1740 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation57) >> >> endobj 1741 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation59) >> >> endobj 1742 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1743 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1744 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1745 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1746 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1747 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1748 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1749 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1750 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1751 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1752 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1753 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1754 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1755 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1711 0 obj << /D [1757 0 R /XYZ 28.346 0 null] >> endobj 1756 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1781 0 obj << /Length 708 /Filter /FlateDecode >> stream xWKO1W̭3O(zzTj5 ;KBf쵃p 'G#k"awǎP%L%Z(N0__V7W#t^.vYb}t ׫Wog槓sf訌`53#{Ϗ*P;o@#F]Ĝ NK|чN2):l\H ) Q&c@m;YG}vΎYs ٔR5{ʈOnWeQ, Eilp6Ev]xW*2wXnm˩! TK*OYY a ms|Z39-_>Dq[xYt!$ꁏ8Q!rW).P`U4z\Sh{,7/9Pv!t3++c;pǎmOi%vWx]'s7Nr9$"RKB V!ɧZKQuR?4mRfǬľo&fyou endstream endobj 1780 0 obj << /Type /Page /Contents 1781 0 R /Resources 1779 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1662 0 R /Annots [ 1759 0 R 1760 0 R 1761 0 R 1762 0 R 1763 0 R 1764 0 R 1765 0 R 1766 0 R 1767 0 R 1768 0 R 1769 0 R 1770 0 R 1771 0 R 1772 0 R 1773 0 R 1774 0 R 1775 0 R 1776 0 R 1777 0 R 1778 0 R ] >> endobj 1759 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation59) >> >> endobj 1760 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1761 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation61) >> >> endobj 1762 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation59) >> >> endobj 1763 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1764 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1765 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation61) >> >> endobj 1766 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1767 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1768 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1769 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1770 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1771 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1772 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1773 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1774 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1775 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1776 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1777 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1778 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1712 0 obj << /D [1780 0 R /XYZ 28.346 0 null] >> endobj 1779 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im28 1180 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1805 0 obj << /Length 992 /Filter /FlateDecode >> stream xWMs<W9D[W 3񾇌㦞ip dnZCC,k_ϳZ'dDO$ `NjV0&b1siApǤXjqLgj5Cx5վĻ7s/(Rt2O:2oyT1L2#P*hM^-APzE X7 \hǯeEY0gLMx&Eu1x;u F&^͘  h5 qo["Qʪi7vyhwv:êbuU}l?v)1lDOz-Ԏ 2V&/Tkx4f7%VjJ0%/J&2#emU7isSvO,W+kcahXoձ^aBLwM qW{]_w@+lg'x<F8Υ}qG~hcHi `rO8%N-DŽ^&Ή(h`1c& 2B}NA9ј g񟨰xJ9[1?OYjP\%;߄nLƛq'2{ Oٚ˿?Ãu!%O%|kLŒtF, 5s g p(p\I]$"{. \a@Wהhu"KJ=(5\?Kb = wYC Ys"!dQ8\cMo+{8\/ v"Í^z?n7BSqF> /Parent 1806 0 R /Annots [ 1783 0 R 1784 0 R 1785 0 R 1786 0 R 1787 0 R 1788 0 R 1789 0 R 1790 0 R 1791 0 R 1792 0 R 1793 0 R 1794 0 R 1795 0 R 1796 0 R 1797 0 R 1798 0 R 1799 0 R 1800 0 R 1801 0 R 1802 0 R ] >> endobj 1783 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1784 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1785 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation62) >> >> endobj 1786 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1787 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation61) >> >> endobj 1788 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation62) >> >> endobj 1789 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation63) >> >> endobj 1790 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1791 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1792 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1793 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1794 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1795 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1796 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1797 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1798 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1799 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1800 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1801 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1802 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1782 0 obj << /D [1804 0 R /XYZ 28.346 0 null] >> endobj 1803 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1831 0 obj << /Length 993 /Filter /FlateDecode >> stream xXr7+8<Bc5UoIሚ*Xߧ Eˋb[>4z{dkzFi@aCa`#[L9#,nf{1,,Vg3ilwc4͡k1w7ӿo?p93^Pdteb@3dFTК pAy(1`N֏? H>;y L? 5BOD&="s5xPG1Hܛ1a34j&á_nh) ~6T;u˰L[BI< dnL^uw˩pͿ[<7)ҬNwssU)9W2[1?R9m'rjm]Zص]Op0c4`,C KJ[3>aBL>6~}{d7kG3y yW1t5fZ2ED<҇ NI$p1ah7O4L)Ark VNU$10Qg{`CDdFI:i ]0+ Sngn5KɅ o&"}/fHxD21$aZD4Ly0aDI{Oҏ\$ hAgTX<œ^{1?OYjl +7@7a7x'{"0xZ<.^~O6.)%}.Yoo[#(k ]TH2' 83AQp\I]$U=y \a@Wהhm"KJ#(-?5ji{CnBC\HY8 |l-}eݖ ^za7zT&N1EI VD9b+$AJAS|> /Parent 1806 0 R /Annots [ 1809 0 R 1810 0 R 1811 0 R 1812 0 R 1813 0 R 1814 0 R 1815 0 R 1816 0 R 1817 0 R 1818 0 R 1819 0 R 1820 0 R 1821 0 R 1822 0 R 1823 0 R 1824 0 R 1825 0 R 1826 0 R 1827 0 R 1828 0 R ] >> endobj 1809 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation61) >> >> endobj 1810 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1811 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation63) >> >> endobj 1812 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation60) >> >> endobj 1813 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation61) >> >> endobj 1814 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation62) >> >> endobj 1815 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation63) >> >> endobj 1816 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1817 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1818 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1819 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1820 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1821 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1822 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1823 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1824 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1825 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1826 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1827 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1828 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1807 0 obj << /D [1830 0 R /XYZ 28.346 0 null] >> endobj 1829 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1854 0 obj << /Length 1113 /Filter /FlateDecode >> stream xXMs6 `Of* %~\4fC⽥=(ZYid? )Rw$M6IR6#W7{0"$Z+NKrvճ 0jRyA6#̈́TIw;I׏^ԻJ^Dr83(̘ٱuߧIގyR>ŽC?88zm Irn[惟ͱǡlpPN"+\XFX&F%)0M1l%yޟ!|Q(8 M̶6“f4x77xS( Z(zW:faisF tmc}|U6K_8 ٦oػJqAѲ rMEpImq1F/YNDl2g2 G*)ؖXO-1^zTW6ixRϲvCikk5WەvrC3\ &ַ~Ryi=rvIO[vS'ԑsJJ1h$[0}/k{-N&/}'ݑTᵞxޓՉ>9Ek)XYbؠTh%@%`}.굵9~a5H0:SL͍1Jxw$`(Pnw$0 JKCfd]Hx4p%͝MQ!j8$)x;~N%04Q x s"p, 0ha2.>Q j}Ω)༵\55 NOhb75s?y"~ƔISz^p Z I2LDB\[̤crSuXh"JWE*J?Y>M@a]($\RgN~Iip,#C *J03')8? m [Wp_؛lE=+ -|b>,B<:)$^4m͊/ZLD{0~f?c햀 endstream endobj 1853 0 obj << /Type /Page /Contents 1854 0 R /Resources 1852 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1806 0 R /Annots [ 1832 0 R 1833 0 R 1834 0 R 1835 0 R 1836 0 R 1837 0 R 1838 0 R 1839 0 R 1840 0 R 1841 0 R 1842 0 R 1843 0 R 1844 0 R 1845 0 R 1846 0 R 1847 0 R 1848 0 R 1849 0 R 1850 0 R 1851 0 R ] >> endobj 1832 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation62) >> >> endobj 1833 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1834 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation64) >> >> endobj 1835 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation62) >> >> endobj 1836 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation63) >> >> endobj 1837 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation64) >> >> endobj 1838 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation65) >> >> endobj 1839 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1840 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1841 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1842 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1843 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1844 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1845 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1846 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1847 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1848 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1849 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1850 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1851 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1808 0 obj << /D [1853 0 R /XYZ 28.346 0 null] >> endobj 1852 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1879 0 obj << /Length 1109 /Filter /FlateDecode >> stream xXr6+Sə\4fCb9#HL? iKijMawv ab#FT Ix)pE5ٮޞ(=tqz 4F 3@[2d!%PERNUz7Gk43c(@A2<3"n4:79'_S;#O٦)/m|C9Vcw^84ݕuʉ+,.V?1@l&$4ZUe&!;:e+]fҘ?wHcd`O3&'Fַ~Ry~8 kLa[vR'%4qRsٻ*M}?A]D`rZI|KW~D10Z[bU4 ն)9x0iKzktNwC{9`QI,#A GvYC`޷/39ɘA4)j aliF(0'9KfaZiKnDysXaOc8dB dQiB8 z&#zΡ)`\55 FKb76s o+ɔ>íg(÷V S HP̸ZLi9+erY.dD[E*",h&#pFXWыD7P*r]"ۯc6A2 euS!> /Parent 1806 0 R /Annots [ 1857 0 R 1858 0 R 1859 0 R 1860 0 R 1861 0 R 1862 0 R 1863 0 R 1864 0 R 1865 0 R 1866 0 R 1867 0 R 1868 0 R 1869 0 R 1870 0 R 1871 0 R 1872 0 R 1873 0 R 1874 0 R 1875 0 R 1876 0 R ] >> endobj 1857 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation63) >> >> endobj 1858 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1859 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation65) >> >> endobj 1860 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation62) >> >> endobj 1861 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation63) >> >> endobj 1862 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation64) >> >> endobj 1863 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation65) >> >> endobj 1864 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1865 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1866 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1867 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1868 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1869 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1870 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1871 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1872 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1873 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1874 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1875 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1876 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1855 0 obj << /D [1878 0 R /XYZ 28.346 0 null] >> endobj 1877 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1902 0 obj << /Length 1174 /Filter /FlateDecode >> stream xXKs6WH͔.qLgzH[&%MDі]H۲cI fވ4"WD&VVLQhvhC/.foޡe܁C`(WJ2WڲŊ}*>KMq췻9ZmWqz?_4`Mϋ3ҡ:JWqX) FR?}_5^TE{saCד"^Kwg㶽5Qtw,ӎcdxP.d;EsȵԑKo$z :f/m@e˙y@$DTkhn *Ӻe'B)5 nm7rNq:|1 i1u7Pc^t7.6]ۭ}]zABCŐ0 =Ohβzv+؎SG-Yhy C\>7LJXNF(`SPe5<U>ۭb.x :oT." Ce cMW>,x Cd}_7BMXaђ㤮jR>RYS{Gv4Xkv1Nq)y%;;!s2G,RvMKk$uGbB|>gUlq*C!p$* UDRQL%Hɴcw;C(89#;n8sI8M=U:o;r`hD'Qd))KqXY!(rIWX"gnLJFauDC*V z"r=Һ&_XPʔH:)3&I@$IGZEdISjrFglc>@ 7y^g Y(Udž{鬃iNw ^a;z!ݔW:,1EɋQY&%> /Parent 1806 0 R /Annots [ 1880 0 R 1881 0 R 1882 0 R 1883 0 R 1884 0 R 1885 0 R 1886 0 R 1887 0 R 1888 0 R 1889 0 R 1890 0 R 1891 0 R 1892 0 R 1893 0 R 1894 0 R 1895 0 R 1896 0 R 1897 0 R 1898 0 R 1899 0 R ] >> endobj 1880 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation64) >> >> endobj 1881 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1882 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation66) >> >> endobj 1883 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation64) >> >> endobj 1884 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation65) >> >> endobj 1885 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation66) >> >> endobj 1886 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation67) >> >> endobj 1887 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1888 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1889 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1890 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1891 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1892 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1893 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1894 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1895 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1896 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1897 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1898 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1899 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1856 0 obj << /D [1901 0 R /XYZ 28.346 0 null] >> endobj 1900 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1927 0 obj << /Length 1169 /Filter /FlateDecode >> stream xXKs6WH͔.qLgzH[&%MDі]H۲n }|45~wFi" 0bBC.f =u|y!p₡P\)j^i+0/6űXj]ɾD_hmgdCOmBR΍&,fjf[^΅-]Ohr^D<8安Vv+$ǃwG 3, D\~˥&#W6~o}G|,Ͷ^ʬ %ZCeu;Q7-^>  '-5 (6Kћ;޴9518E# qn80wۺ4>]P )0W:ZRqaG3m1YvX[.y۱s:[BKE|>,We> tt`h cq4Et2BvX/N {>/U =d ٠*rD Hf|) ǐe,v f ׇ.-9P=<85ZvX;?ߏ7RW:gv**/bT$kB\Z#B9}RVǩ>"rJe"PDw,P͂/QmD01M#n8sI8MY:; `hD'Q0R)S$2qXY!(rI!VX"gaLFFOa LC=*"H;+vp%)o}5@fINDS-~9j!l>)kON))}nN]#]'dIG}:#I7)}x=}̴Ղ\iEo)2%*NFLAn%зOҀ}J@3D0{lSx|*CNh ܔ7:,1EɋX&%> /Parent 1806 0 R /Annots [ 1905 0 R 1906 0 R 1907 0 R 1908 0 R 1909 0 R 1910 0 R 1911 0 R 1912 0 R 1913 0 R 1914 0 R 1915 0 R 1916 0 R 1917 0 R 1918 0 R 1919 0 R 1920 0 R 1921 0 R 1922 0 R 1923 0 R 1924 0 R ] >> endobj 1905 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation65) >> >> endobj 1906 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1907 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation67) >> >> endobj 1908 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation64) >> >> endobj 1909 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation65) >> >> endobj 1910 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation66) >> >> endobj 1911 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation67) >> >> endobj 1912 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1913 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1914 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1915 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1916 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1917 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1918 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1919 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1920 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1921 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1922 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1923 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1924 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1903 0 obj << /D [1926 0 R /XYZ 28.346 0 null] >> endobj 1925 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1950 0 obj << /Length 1214 /Filter /FlateDecode >> stream xXKo9 W8vRo] (P]V;v~ ~)i;c'Mn5HJD-#8YV(Ḯa9}|$_h1T aEngS~XOǵ"[UDm) q>f~zX7;Ićg\ WwEϷ%'/lSntLvtȺhjџwK(˚uw٬Y[' v}Cg86Yݿ䫱vVS5۱ jwț6zo/[oVÚ&Y!`xJqTroMpg`3:!,h[(y>i h0΄qM"SYţP,z&;XH0b Ys֛B"Eǵ{pO׆d=_+k8> /Parent 1951 0 R /Annots [ 1928 0 R 1929 0 R 1930 0 R 1931 0 R 1932 0 R 1933 0 R 1934 0 R 1935 0 R 1936 0 R 1937 0 R 1938 0 R 1939 0 R 1940 0 R 1941 0 R 1942 0 R 1943 0 R 1944 0 R 1945 0 R 1946 0 R 1947 0 R ] >> endobj 1928 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation66) >> >> endobj 1929 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1930 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation68) >> >> endobj 1931 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation66) >> >> endobj 1932 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation67) >> >> endobj 1933 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation68) >> >> endobj 1934 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation69) >> >> endobj 1935 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1936 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1937 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1938 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1939 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1940 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1941 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1942 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1943 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1944 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1945 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1946 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1947 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1904 0 obj << /D [1949 0 R /XYZ 28.346 0 null] >> endobj 1948 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F16 42 0 R /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1976 0 obj << /Length 1209 /Filter /FlateDecode >> stream xXKo8W(+fo^ t (nr+zpeb(wHNxi8726gލhEZ{Fp'5VpmgvЯonFWa܃Gvs˄R&Շ|5RʊڇoUvYǵR&ڇ~qפ$zm_nޓ5JO^*U5Y;ɘmgnu742;YEK7wK(˚Uw٬X{$O2P,4~Cg86ٺYP7jN XKMMfֳ]Y5uaEȐ40r_guP|\ W*#iӕp^߭ߗi&e: ťDq/aT!M 4/t 4.`UoٝFKoLIMlqԂK2pyj08Z0Geߤ)ӕxVrנs_αQy+nd2\xgl@(PSpAq- \:KYb:<ѯSrhD(jM$= He]CC$ զC)L}ȭ#g 0alht[C0/#)L\ә>Q hBv縁Ľʄ'GHHG 9?2,^aڇj&nP\JV fx;;Ymaxx RK87ȔExzE"Xu$Q:Gf!(8e=>!,P"kl)N¢s&<[y/2U<a ~Ϻ {X0!wzS(Yvڐ-ue ǽݔ ^/c`Mb6S6BpVޅ6v2hC2>D%Q./,#_+ endstream endobj 1975 0 obj << /Type /Page /Contents 1976 0 R /Resources 1974 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1951 0 R /Annots [ 1954 0 R 1955 0 R 1956 0 R 1957 0 R 1958 0 R 1959 0 R 1960 0 R 1961 0 R 1962 0 R 1963 0 R 1964 0 R 1965 0 R 1966 0 R 1967 0 R 1968 0 R 1969 0 R 1970 0 R 1971 0 R 1972 0 R 1973 0 R ] >> endobj 1954 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation67) >> >> endobj 1955 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1956 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation69) >> >> endobj 1957 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation66) >> >> endobj 1958 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation67) >> >> endobj 1959 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation68) >> >> endobj 1960 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation69) >> >> endobj 1961 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1962 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1963 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1964 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1965 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1966 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1967 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1968 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1969 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1970 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1971 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1972 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1973 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1952 0 obj << /D [1975 0 R /XYZ 28.346 0 null] >> endobj 1974 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F16 42 0 R /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1999 0 obj << /Length 996 /Filter /FlateDecode >> stream xXn9+xl]ŝ3 !nAF[$DN0#n˲D(k{LVx312ƏNɠP^IVNfѷ9&)Xe %8:X\]ݿәvnф4N55C'fnڮrWkg#5݌@"agFɨ ]O qKAR ˚뤭5Q܋91>6Q2A&~ZW Mgt9S.@ Sċ8p9cݱdF۳ `rmn?_MUȕӺ3aN$33#8GP{n:S|6YJBX \}ZݵbXgz/ʄA4%JQaŲ48ftt.^4c3.p89V^Aujmml'F;ąG5I:BbVNAD@>B['y&^2G7Ԏ8I'Ie,`GO,k-lVb6Y#= =^YL'o:ދ>1jHP0'`GEilu6Y.M8'1aCy#OhWVD̹ƥ\N{]OgqRh,AO񯨰:$mas~YQ|e~o (RS7Pg twS<|%M-kʋߠѺ?9~rI,d.F9$P-!*ILg\Jϼ")KJ?/WSH(fQ$5 Vl_aYI=K"!RJ+Il wlai|K_njpans]r>㩓!X|uI8 O4P1c #ˤ,_r endstream endobj 1998 0 obj << /Type /Page /Contents 1999 0 R /Resources 1997 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1951 0 R /Annots [ 1977 0 R 1978 0 R 1979 0 R 1980 0 R 1981 0 R 1982 0 R 1983 0 R 1984 0 R 1985 0 R 1986 0 R 1987 0 R 1988 0 R 1989 0 R 1990 0 R 1991 0 R 1992 0 R 1993 0 R 1994 0 R 1995 0 R 1996 0 R ] >> endobj 1977 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation68) >> >> endobj 1978 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 1979 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation70) >> >> endobj 1980 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation68) >> >> endobj 1981 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation69) >> >> endobj 1982 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation69) >> >> endobj 1983 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation70) >> >> endobj 1984 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1985 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1986 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1987 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1988 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1989 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1990 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1991 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1992 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 1993 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 1994 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 1995 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 1996 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 1953 0 obj << /D [1998 0 R /XYZ 28.346 0 null] >> endobj 1997 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2024 0 obj << /Length 1240 /Filter /FlateDecode >> stream xXKs6WV cn3iɡ큡iHƔ.lq6nNϞK+Z!Ï1A:pT󜀠 ) Ya'3:$'b(זYAɅ )s8uRFe,$e+4Qx7$pH"_x L#T0qZϙC0MS BgsԠIGp"EP>ϑШ2'P|w NP#c(F## laFs3OF137n70=J'v&jqQ Qτ? ko|ٌ3O?̈}~D^hwLY4#IPPjG.dh16i^"I%^)8FD1 ILVFɋHInFwB):;G_\~e)ˈ/]=2Q02OQ~cM+j]e:y_\kwyJ6LSv!h,?I::!AxGJ3Iƃ2EŧQ%.bP+zGIյ}=,^7@^vxÈڄYK w aqGD6s1Z3WXyt/ʽ2m0)nSW/Lr hqe Όs8ZK~\ g?.WΪMhۢ|ww2̻yXة n8ʩAM9v1.@O5_ź3Z!ӭ>vs-znL#J BG߽.53yY]~BݶQTB쯞um Dt^,(;+) 3sCIYHެ ]l]|} ˮnbfQy߷;5´ t6_u]zTk~_|,+ Wݾ^K*[j %vXos* p{9(n ;J0yp}#?G}0i c@]B6OhTWfW'KXֽm>m TDW% endstream endobj 2023 0 obj << /Type /Page /Contents 2024 0 R /Resources 2022 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1951 0 R /Annots [ 2001 0 R 2002 0 R 2003 0 R 2004 0 R 2005 0 R 2006 0 R 2007 0 R 2008 0 R 2009 0 R 2010 0 R 2011 0 R 2012 0 R 2013 0 R 2014 0 R 2015 0 R 2016 0 R 2017 0 R 2018 0 R 2019 0 R 2020 0 R 2021 0 R ] >> endobj 2001 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation69) >> >> endobj 2002 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 2003 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation71) >> >> endobj 2004 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation69) >> >> endobj 2005 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation70) >> >> endobj 2006 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation70) >> >> endobj 2007 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation71) >> >> endobj 2008 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2009 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2010 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2011 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2012 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2013 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2014 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2015 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2016 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2017 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2018 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 2019 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 2020 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 2021 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation1) >> >> endobj 2000 0 obj << /D [2023 0 R /XYZ 334.488 0 null] >> endobj 2025 0 obj << /D [2023 0 R /XYZ 334.488 0 null] >> endobj 2022 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm1 12 0 R /Fm5 53 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2049 0 obj << /Length 716 /Filter /FlateDecode >> stream xWQo1 ~_`'\۴ƤJ|\cv9Ew$$ `Mt-֟93z|h^&a"X\֠@p28u49:7W.t,YvQHTc2%)9Owg%8k:LP0bobpY_oV_7ojJU旜M}KA> a3 -4{p+C.ŖYI460Rθ9[)c^0w؟7ȿV2RE[53-KLjjG1#42T[e͒=vd׉ &u. w)Ǘ8*fdUJ%n̻NG|:^dX=0֘'ϠoGzYKJ/Mֿ5~ bɺ! _aQ% I F)@KB 29|pes."zDoAǺH_k#z*55tܗ()a=*=|)~*9g{IJ)Y|B0ȁ,Z rͲ6]ٳmqV_alR? [nvrv$<.uO k XWJԉnEʇMVv̪hјHqf2.Ty endstream endobj 2048 0 obj << /Type /Page /Contents 2049 0 R /Resources 2047 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1951 0 R /Annots [ 2027 0 R 2028 0 R 2029 0 R 2030 0 R 2031 0 R 2032 0 R 2033 0 R 2034 0 R 2035 0 R 2036 0 R 2037 0 R 2038 0 R 2039 0 R 2040 0 R 2041 0 R 2042 0 R 2043 0 R 2044 0 R 2045 0 R 2046 0 R ] >> endobj 2027 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation70) >> >> endobj 2028 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2029 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2030 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation70) >> >> endobj 2031 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation71) >> >> endobj 2032 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation71) >> >> endobj 2033 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2034 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2035 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2036 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2037 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2038 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2039 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2040 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2041 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2042 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2043 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2044 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2045 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2046 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2026 0 obj << /D [2048 0 R /XYZ 28.346 0 null] >> endobj 2047 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2073 0 obj << /Length 995 /Filter /FlateDecode >> stream xWKo7Wb`X)@@֒KBVJ~$E^:Ia¾8`h̋ oP%8׬51_Xͪ!K%_n{HpߏC&7AIź+~%/%v5~@1O$\T^ o g)6>d%*VKdLfy?F9 endstream endobj 2072 0 obj << /Type /Page /Contents 2073 0 R /Resources 2071 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 1951 0 R /Annots [ 2051 0 R 2052 0 R 2053 0 R 2054 0 R 2055 0 R 2056 0 R 2057 0 R 2058 0 R 2059 0 R 2060 0 R 2061 0 R 2062 0 R 2063 0 R 2064 0 R 2065 0 R 2066 0 R 2067 0 R 2068 0 R 2069 0 R 2070 0 R ] >> endobj 2051 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation71) >> >> endobj 2052 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2053 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2054 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation71) >> >> endobj 2055 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2056 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2057 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2058 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2059 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2060 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2061 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2062 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2063 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2064 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2065 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2066 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2067 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2068 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2069 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2070 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2050 0 obj << /D [2072 0 R /XYZ 28.346 0 null] >> endobj 2071 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F24 1317 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2102 0 obj << /Length 834 /Filter /FlateDecode >> stream xWKo1W̱km!47Z*T"ٻcoҥD)^n?Ͱw&b &z|5Jfn*cEH(sa)MT!DZN^j SuufXg{4] E `׷bsk[<\I{sBPI 4c b+WF$I*t52R,O樶:B(=^[M.лtBƟi{F{j(v0a}Z\R@6EO)Devi&T2v֒kO -e-ABqK)EZ)#Id-%8'"4U|q6ERg@QTlʱ빤p02|Σ1e3h^ \ k$/b?q(Ft56Ra|꺀U*%x׬ tSBc(BݠK7xto#LPecæhyr JKy?9n_Oz[n 8P5!kUxd{6.,Dx .غW0Zaʀ)y8*6dW/n ŕPzzWyZx'jg,oTN^8u.U+ .n[Zal7~."0Fg&9%ܕxSa!o!qeR?4c2ӨOC2v_&aonw endstream endobj 2101 0 obj << /Type /Page /Contents 2102 0 R /Resources 2100 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2103 0 R /Annots [ 2080 0 R 2081 0 R 2082 0 R 2083 0 R 2084 0 R 2085 0 R 2086 0 R 2087 0 R 2088 0 R 2089 0 R 2090 0 R 2091 0 R 2092 0 R 2093 0 R 2094 0 R 2095 0 R 2096 0 R 2097 0 R 2098 0 R 2099 0 R ] >> endobj 2075 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/con1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2104 0 R /BBox [77.469 367.8 288.2 528.199] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 2106 0 R /F7 2108 0 R /F8 2110 0 R /F11 2112 0 R /F14 2114 0 R /F15 2116 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2117 0 R /Pat96 2118 0 R >>>> /Length 510 /Filter /FlateDecode >> stream xTMo@ W=sz"7ʉ-V 8&&Y!$)8/oLp ߫g? cVPS _!"u.YO˺z#Z C}W})p3Unv(r FQX,%!ۺΔwr4@mʯ.%CBˡ4)Lt(a*;yD4YYrK39RMIК&ƘHz5;Uhp9OI{658QRqUtKqnJWΩFSFFb/L49#:vTz3f{Uj'mAQZ r_0xNL8db"bƤi)}]K>6~:bB]y;T=㹭5!GL)Kf};r{_Tz 9Y-6DmU/v@ f(1ǒʼG7]}7U endstream endobj 2104 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212155654) >> endobj 2106 0 obj << /Type /Font /Subtype /Type1 /FirstChar 2 /LastChar 3 /Widths [ 416.7 416.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 2105 0 R >> endobj 2108 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 2107 0 R >> endobj 2110 0 obj << /Type /Font /Subtype /Type1 /FirstChar 40 /LastChar 50 /Widths [ 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 2109 0 R >> endobj 2112 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 2111 0 R >> endobj 2114 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 1 /Widths [ 777.8 277.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 2113 0 R >> endobj 2116 0 obj << /Type /Font /Subtype /Type1 /FirstChar 58 /LastChar 110 /Widths [ 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 2115 0 R >> endobj 2117 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2118 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2115 0 obj << /Type /Encoding /Differences [58/colon 80/P 100/d/e 103/g 105/i 110/n] >> endobj 2113 0 obj << /Type /Encoding /Differences [0/minus/periodcentered] >> endobj 2111 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 2109 0 obj << /Type /Encoding /Differences [40/parenleft/parenright 43/plus 49/one/two] >> endobj 2107 0 obj << /Type /Encoding /Differences [50/two] >> endobj 2105 0 obj << /Type /Encoding /Differences [2/bracketleftbig/bracketrightbig] >> endobj 2080 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2081 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2082 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation74) >> >> endobj 2083 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2084 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2085 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2086 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2087 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2088 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2089 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2090 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2091 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2092 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2093 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2094 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2095 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2096 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2097 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2098 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2099 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2074 0 obj << /D [2101 0 R /XYZ 28.346 0 null] >> endobj 2100 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im30 2075 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2144 0 obj << /Length 835 /Filter /FlateDecode >> stream xWKo1W̱km!47Z*T"ٻcoҥD)^n?Ͱw&b &z|5Jfn*cEH(sa)MT!DZN^j SuufXg{4] E `׷bsk[<\I{sBPI 4c b+WF$I*t52R,OBV.$Z:˪h=^[hkW~O==q;0QqtZ\R@6EO)Devi&2v֒k -e-ABuK)EZ)#Id-T%8'"4U|q6ERg@QTlʱ빤u*E|PȈG:8NĔy:+p]J4H|BYxHi _TIV3_*Na %:w.zFI͎0A}ʒA-(/ںTY?Mm5>@ՄlM\TIѲnU5^@ظAp.`G.vWD^ k1W$W\MQ!z!HuS(ӻ;AP;c@xG.rBƁsz_DV_v=t% gvai7z=\6ɡ,SXğ- y ,ې_FUxH2ˏ}ؗ endstream endobj 2143 0 obj << /Type /Page /Contents 2144 0 R /Resources 2142 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2103 0 R /Annots [ 2122 0 R 2123 0 R 2124 0 R 2125 0 R 2126 0 R 2127 0 R 2128 0 R 2129 0 R 2130 0 R 2131 0 R 2132 0 R 2133 0 R 2134 0 R 2135 0 R 2136 0 R 2137 0 R 2138 0 R 2139 0 R 2140 0 R 2141 0 R ] >> endobj 2076 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/con2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2145 0 R /BBox [221.469 431.8 432.2 592.199] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 2147 0 R /F7 2149 0 R /F8 2151 0 R /F11 2153 0 R /F14 2155 0 R /F15 2157 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2158 0 R /Pat96 2159 0 R >>>> /Length 588 /Filter /FlateDecode >> stream xUMo@W1e3;űAOyĎԈVwG$y#S䐌B}wKGE{Lٳa9[5pi)vYhuӼ[9!ʹ|~urM˦|jT4yPH92cgaeLG* <(+,^%m *AXd+hԮDOn@Gu,p4O;{d-C'˔p&ˮ(ΌyΩo^77j`g1ɬX[\"h6ES/(״zmRcx*\B8P'_9PJ/ $O2[Djg+Q>ג #;5BR 0G͏qh8Fw흕H_xhvnfЀeDg/{5+GK)+Zt[xWi7I-WzWaciM0Hۆ%΅#PyD3hE?3:tѢ>oB"ynDU9.|<%Y;oh7Go( endstream endobj 2145 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212155708) >> endobj 2147 0 obj << /Type /Font /Subtype /Type1 /FirstChar 2 /LastChar 21 /Widths [ 416.7 416.7 472.2 472.2 472.2 472.2 583.3 583.3 472.2 472.2 333.3 555.6 577.8 577.8 597.2 597.2 736.1 736.1 527.8 527.8] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 2146 0 R >> endobj 2149 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 2148 0 R >> endobj 2151 0 obj << /Type /Font /Subtype /Type1 /FirstChar 40 /LastChar 50 /Widths [ 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 2150 0 R >> endobj 2153 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 2152 0 R >> endobj 2155 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 1 /Widths [ 777.8 277.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 2154 0 R >> endobj 2157 0 obj << /Type /Font /Subtype /Type1 /FirstChar 58 /LastChar 110 /Widths [ 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 2156 0 R >> endobj 2158 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2159 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2156 0 obj << /Type /Encoding /Differences [58/colon 80/P 100/d/e 103/g 105/i 110/n] >> endobj 2154 0 obj << /Type /Encoding /Differences [0/minus/periodcentered] >> endobj 2152 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 2150 0 obj << /Type /Encoding /Differences [40/parenleft/parenright 43/plus 48/zero/one/two] >> endobj 2148 0 obj << /Type /Encoding /Differences [50/two] >> endobj 2146 0 obj << /Type /Encoding /Differences [2/bracketleftbig/bracketrightbig 20/bracketleftbigg/bracketrightbigg] >> endobj 2122 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2123 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2124 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation75) >> >> endobj 2125 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2126 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2127 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2128 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2129 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2130 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2131 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2132 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2133 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2134 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2135 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2136 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2137 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2138 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2139 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2140 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2141 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2119 0 obj << /D [2143 0 R /XYZ 28.346 0 null] >> endobj 2142 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im31 2076 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2183 0 obj << /Length 835 /Filter /FlateDecode >> stream xWKo1W̱km!47Z*T"ٻcoҥD)^n?Ͱw&b &z|5Jfn*cEH(sa)MT!DZN^j SuufXg{4] E `׷bsk[<\I{sBPI 4c b+WF$I*t52R,OBV.$Z:˪h=^[C.м״BƟi{F{j(v0a"O3l>SVvL(e%!>Z> /Parent 2103 0 R /Annots [ 2161 0 R 2162 0 R 2163 0 R 2164 0 R 2165 0 R 2166 0 R 2167 0 R 2168 0 R 2169 0 R 2170 0 R 2171 0 R 2172 0 R 2173 0 R 2174 0 R 2175 0 R 2176 0 R 2177 0 R 2178 0 R 2179 0 R 2180 0 R ] >> endobj 2077 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/con3.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2184 0 R /BBox [221.469 431.8 432.2 592.199] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 2186 0 R /F7 2188 0 R /F8 2190 0 R /F11 2192 0 R /F14 2194 0 R /F15 2196 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2197 0 R /Pat96 2198 0 R >>>> /Length 600 /Filter /FlateDecode >> stream xUnAWy2H$RND}kY̴jn[h>(~8)߶i<\7ULPNusq @֟-6&u>!w7KOw_6`}gBMBv!Lw[-c)]pqv;lP.608qn{4Т \ - m]V=G$v"=HKxN:TI,O_)I{Zzϩ9$`5:Jǡ W$ s%k479C4JV྾Iyk+1#g ܭ A_d}8\@l%LE.'‹Ya]MwX~\ [y,BY!U䑯E,fXW/ADpJ E<߬Qu,ĿW;{5ȢBߏQ>358d3V̯&Ic?#'fAZX,)j|iW2Mͭh:0Z(ٽLIMO,lxlo b(oKS cP endstream endobj 2184 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212155727) >> endobj 2186 0 obj << /Type /Font /Subtype /Type1 /FirstChar 20 /LastChar 53 /Widths [ 527.8 527.8 583.3 583.3 583.3 583.3 750 750 750 750 1044.4 1044.4 791.7 791.7 583.3 583.3 638.9 638.9 638.9 638.9 805.6 805.6 805.6 805.6 1277.8 1277.8 811.1 811.1 875 875 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 2185 0 R >> endobj 2188 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 2187 0 R >> endobj 2190 0 obj << /Type /Font /Subtype /Type1 /FirstChar 43 /LastChar 50 /Widths [ 777.8 277.8 333.3 277.8 500 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 2189 0 R >> endobj 2192 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 2191 0 R >> endobj 2194 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 2193 0 R >> endobj 2196 0 obj << /Type /Font /Subtype /Type1 /FirstChar 58 /LastChar 110 /Widths [ 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 2195 0 R >> endobj 2197 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2198 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2195 0 obj << /Type /Encoding /Differences [58/colon 80/P 100/d/e 103/g 105/i 110/n] >> endobj 2193 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 2191 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 2189 0 obj << /Type /Encoding /Differences [43/plus 48/zero/one/two] >> endobj 2187 0 obj << /Type /Encoding /Differences [50/two] >> endobj 2185 0 obj << /Type /Encoding /Differences [20/bracketleftbigg/bracketrightbigg 50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt] >> endobj 2161 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation74) >> >> endobj 2162 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2163 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation76) >> >> endobj 2164 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2165 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2166 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2167 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2168 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2169 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2170 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2171 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2172 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2173 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2174 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2175 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2176 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2177 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2178 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2179 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2180 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2160 0 obj << /D [2182 0 R /XYZ 28.346 0 null] >> endobj 2181 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im32 2077 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2222 0 obj << /Length 835 /Filter /FlateDecode >> stream xWKo1W̱km!47Z*T"ٻcoҥD)^n?Ͱw&b &z|5Jfn*cEH(sa)MT!DZN^j SuufXg{4] E `׷bsk[<\I{sBPI 4c b+WF$I*t52R,OBV.$Z:˪h=^[K.м״BƟi{F{j(v0a"O3l>SVvL(eુk -e-ABuK)EZ)#Id-T%8'"4U|q6ERg@QTlʱ빤u*E|PȈG:8NĔy:+p]J4H|BYxHi _TIV3_*Na %:w.zFI͎0A}ʒA-(/ںTY?Mm5>@ՄlM\TIѲnU5^@ظAp.`G.vWD^ k1W$W\MQ!z!HuS(ӻ;AP;c@xG.rBƁsz_DV_v=t% gvai7z=\6ɡ,SXğ- y ,ې_FUxH2ˏ}ؙ endstream endobj 2221 0 obj << /Type /Page /Contents 2222 0 R /Resources 2220 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2103 0 R /Annots [ 2200 0 R 2201 0 R 2202 0 R 2203 0 R 2204 0 R 2205 0 R 2206 0 R 2207 0 R 2208 0 R 2209 0 R 2210 0 R 2211 0 R 2212 0 R 2213 0 R 2214 0 R 2215 0 R 2216 0 R 2217 0 R 2218 0 R 2219 0 R ] >> endobj 2078 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/con4.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2223 0 R /BBox [221.469 431.8 432.2 592.199] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 2225 0 R /F7 2227 0 R /F8 2229 0 R /F11 2231 0 R /F14 2233 0 R /F15 2235 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2236 0 R /Pat96 2237 0 R >>>> /Length 639 /Filter /FlateDecode >> stream xVMo0WEx<6JROT 8hϳ&[6DV1f\g~txZa$H"n)OLt\vSML.v‰ɔflrf}}/7oWR[w *A_OQGa9wL[.Dʩ Sj?. $+RaJOR0qyF ]"*Vv1;#y;f ,eÒQι$,!yى5}H]MϚ鷩]y(v~LN^ŗbGw3^Whϙ$/mT!Ӊ?߻S*0/ 0+M0<Hvi.a(mZJB T>eʨu=XVϦx$9܄h|gw8פ-Ziz3(#(qøimB[ՔrCU`! n&R)hOC'Kj,nSLJHKK3Zؑg^-5A%V^ kUo [KQoOTD)=^"_ endstream endobj 2223 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212155747) >> endobj 2225 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 2224 0 R >> endobj 2227 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 2226 0 R >> endobj 2229 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 50 /Widths [ 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 2228 0 R >> endobj 2231 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 2230 0 R >> endobj 2233 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 2232 0 R >> endobj 2235 0 obj << /Type /Font /Subtype /Type1 /FirstChar 58 /LastChar 110 /Widths [ 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 2234 0 R >> endobj 2236 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2237 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2234 0 obj << /Type /Encoding /Differences [58/colon 80/P 100/d/e 103/g 105/i 110/n] >> endobj 2232 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 2230 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 2228 0 obj << /Type /Encoding /Differences [48/zero/one/two] >> endobj 2226 0 obj << /Type /Encoding /Differences [50/two] >> endobj 2224 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 2200 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation75) >> >> endobj 2201 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2202 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2203 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2204 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2205 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2206 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2207 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2208 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2209 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2210 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2211 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2212 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2213 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2214 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2215 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2216 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2217 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2218 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2219 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2199 0 obj << /D [2221 0 R /XYZ 28.346 0 null] >> endobj 2220 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R >> /XObject << /Im33 2078 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2260 0 obj << /Length 975 /Filter /FlateDecode >> stream xWK9W*fOH a3%|v',/%nGfhƷSVr Nr!-^/ggx KԆly?oWOʺyYnڬW7)@+me5\JreV3zQXx?Yx9)8-&h3Z#D40 ;YHgG83]Cl|ΝTyThV?sؒ,MhCDG00ѕuFڬ0΋G) OJtY#5qkUq.~9~|&})tm+fW7t1CGE"j6eh;ۜgxk}롿HM!Uf|rKs=۾fG\fw *D*xޱh⹴U N)&$s΢lD@z[vZ!x)JdoXA0*Hbj>IȰ( 3ϧn4k ͉<8b44=(@o#%M endstream endobj 2259 0 obj << /Type /Page /Contents 2260 0 R /Resources 2258 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2103 0 R /Annots [ 2238 0 R 2239 0 R 2240 0 R 2241 0 R 2242 0 R 2243 0 R 2244 0 R 2245 0 R 2246 0 R 2247 0 R 2248 0 R 2249 0 R 2250 0 R 2251 0 R 2252 0 R 2253 0 R 2254 0 R 2255 0 R 2256 0 R 2257 0 R ] >> endobj 2079 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/con5.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2261 0 R /BBox [223.8 439.597 432.2 500.339] /Resources << /ProcSet [ /PDF /Text ] /Font << /F1 2263 0 R /F7 2265 0 R /F8 2267 0 R /F11 2269 0 R /F14 2271 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2272 0 R /Pat96 2273 0 R >>>> /Length 386 /Filter /FlateDecode >> stream xڝT=O0 +fނ k ׎#p\<\mj_'F|QipޅK"X3gvc 2V sU̔颛IP\"aּVbB3[umB-=gYgaR1U[Id[#~CIv {o١3N\&,ʌǵXU]r1.biAtR$6ˬ4_aV{8% b-a VВq2}qhQv(FuQ= %>\X$0Y[[t4n'_}SOs98K}p7 endstream endobj 2261 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212160035) >> endobj 2263 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 55 /Widths [ 666.7 666.7 666.7 666.7 666.7 666.7] /FontDescriptor 211 0 R /BaseFont 224 0 R /Encoding 2262 0 R >> endobj 2265 0 obj << /Type /Font /Subtype /Type1 /FirstChar 50 /LastChar 50 /Widths [ 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 2264 0 R >> endobj 2267 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 50 /Widths [ 500 500 500] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 2266 0 R >> endobj 2269 0 obj << /Type /Font /Subtype /Type1 /FirstChar 120 /LastChar 121 /Widths [ 571.5 490.3] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 2268 0 R >> endobj 2271 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 0 /Widths [ 777.8] /FontDescriptor 176 0 R /BaseFont 184 0 R /Encoding 2270 0 R >> endobj 2272 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2273 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2270 0 obj << /Type /Encoding /Differences [0/minus] >> endobj 2268 0 obj << /Type /Encoding /Differences [120/x/y] >> endobj 2266 0 obj << /Type /Encoding /Differences [48/zero/one/two] >> endobj 2264 0 obj << /Type /Encoding /Differences [50/two] >> endobj 2262 0 obj << /Type /Encoding /Differences [50/bracketlefttp/bracketrighttp/bracketleftbt/bracketrightbt/bracketleftex/bracketrightex] >> endobj 2238 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation76) >> >> endobj 2239 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2240 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2241 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation72) >> >> endobj 2242 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation73) >> >> endobj 2243 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2244 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2245 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2246 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2247 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2248 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2249 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2250 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2251 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2252 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2253 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2254 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2255 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2256 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2257 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2120 0 obj << /D [2259 0 R /XYZ 28.346 0 null] >> endobj 2258 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F19 41 0 R /F54 163 0 R /F16 42 0 R /F45 164 0 R /F44 165 0 R /F39 78 0 R >> /XObject << /Im34 2079 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2296 0 obj << /Length 1050 /Filter /FlateDecode >> stream xXKo7W7 NgH.@@H[ۃmUlI;$z; &s97áZ8[d%^[PFSVI#6j?JNGOb}%48DIJ/R.vEM}pܼ^~X[ hoE%-wIͦc9۷ۋ! +?v$;.c8)=Ïs:B0.s=b _]EW(ǛMh?3Nʂ2D0kBK?/k?NB:P BmhemiEzj$ ?@3ilrdnyo\𫊖qopF5dCz@EOx sS˟ƊPe{(,WF Ө}@j ;V.٨.^2੸\L.CB;5&u7AO̹Ik5q3 .wfIC%"֘:fm1lg #kiIƭFZ=ҺiOaMwbByuV` aX ibF)wx+i"$`c9+PrJf"D<AiޝP;֧e9kYSȲDQP•a r"Fi,|{:s], 68] 84nRv1IJO(aD#Ѱ N/G%6r>?old } ̳[kx>%epdm0L7+;ɚX|%l 4/;qV̐W &vzqH21O0T̙>H3㌔6yp.jUJ~Ud y4B5 <|xngy/2U<7E9gz,T:sE4!wF),Rw6,q> /Parent 2103 0 R /Annots [ 2274 0 R 2275 0 R 2276 0 R 2277 0 R 2278 0 R 2279 0 R 2280 0 R 2281 0 R 2282 0 R 2283 0 R 2284 0 R 2285 0 R 2286 0 R 2287 0 R 2288 0 R 2289 0 R 2290 0 R 2291 0 R 2292 0 R 2293 0 R ] >> endobj 2274 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2275 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2276 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2277 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2278 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2279 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2280 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2281 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2282 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2283 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2284 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2285 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2286 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2287 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2288 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2289 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2290 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2291 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2292 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2293 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2121 0 obj << /D [2295 0 R /XYZ 28.346 0 null] >> endobj 2294 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F24 1317 0 R /F45 164 0 R /F36 1316 0 R /F40 605 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2321 0 obj << /Length 1047 /Filter /FlateDecode >> stream xXKo7W7 3$P@k @ $-A]˶*Kjhb.J8h%^PFSVI#n7rǮf?FNGObu)48DIJ.īqTΏfAͲ޷f^%ys3KiKζo7-)5oٮw$PhZ',pP:t0.s5b_C:Uz=$z>ibw"/.&SsAs`fP#?AD@YY?Q8Ad`9Kl\x9dtzcy{^O01=r͹\WCr*;S UfSr`8 |j2cۺD@U))]<Ma uxrAEէ@;58MwA ܨ}L.Fġz|~- miI}s?- 09q{%FgE?y pN!P7bv_L(eDq MLX \ɒ0WErZtw'i`,< :>S$6ĩ1EɄO揱lD91I_ _#s2[kxa`Lz!졸JVބjX }dYoo'kb񡖰5`:ϟ@J?**/R&Sj;O|O8P$G*LRGo$uqFJG ZU_YCg#uGME&FŋL)nfsB*@Gq΢&4dY EJ~ךe=t֕5{.^~`'zXn:$Ԁlzc)ᬼD6r㛇e|@%  ӗIj{/K endstream endobj 2320 0 obj << /Type /Page /Contents 2321 0 R /Resources 2319 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2322 0 R /Annots [ 2299 0 R 2300 0 R 2301 0 R 2302 0 R 2303 0 R 2304 0 R 2305 0 R 2306 0 R 2307 0 R 2308 0 R 2309 0 R 2310 0 R 2311 0 R 2312 0 R 2313 0 R 2314 0 R 2315 0 R 2316 0 R 2317 0 R 2318 0 R ] >> endobj 2299 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2300 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2301 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2302 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation77) >> >> endobj 2303 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation78) >> >> endobj 2304 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2305 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2306 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2307 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2308 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2309 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2310 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2311 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2312 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2313 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2314 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2315 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2316 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2317 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2318 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2297 0 obj << /D [2320 0 R /XYZ 28.346 0 null] >> endobj 2319 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F24 1317 0 R /F45 164 0 R /F36 1316 0 R /F40 605 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2345 0 obj << /Length 1521 /Filter /FlateDecode >> stream xn6_X~) X hAQؘd`CR$NI /xt7!Ja~A\1lDL3LB5:}/GA`K,EGH0 1!1aj]Zr-8_ԋ޾|\ H; (S k0JKܮ`W75vRb *6PvF^Ka?kbĽ`XzrAjQnmrFR zd*'0v|R:bu, ͱɽ2BPEbCN'm_c'z4sVDf0 1"07j20jQ(zb 7#QK i)7!@]]7!Bݦp5}߭UuӴ<^r7.w%F~lË< H 9omv]6)vL!>T6E/nsޏT{*vKCާcŁ"D# ՐSç1*1V"/R9\V܈IrlfC}jQoVI}U@bSg` S+Yq5EhBʈtR2)>Xth3b*p 1$|iN;W5!]ۗ姺orGdžkMP:@=`- 112s&/8{7]6.Tz{yl1ڱǪr۟fUמ_֛l2UʊXVlRV^`HV (XB<`@ j}޶3?4J|Cqޭr 9-9 !#88@e1&S 4t:G?fs<,4& @ÝExx M!TyHo]"nt DP}N?Awn^LڽBˇd×Ʌjܞ F?eacLXjWpGA3g.\\~fʠn$ghğZ; eP3t naB`|S x0 73@D/K4਌@A ~@G`֠89Kk"Vh p#ˆ4& 츍Lm8=Od䜦 r Fs'B8f0#e9u[i6?7s;i291 @oav,ם+d;,hEz'Fӛ.φ!gANc.n;p e&;pmܿYO+99Iz܎Fl%*E`|erqL%~L8)fOp |a2A"r(J 4qJP4ʈ*i!I3S*J|h1 %WmzQ,_+d|JG^~mWg)~p`NT>݄=-r ,>:*&$Kǐh4YV%,:6gLo&Xn߀ endstream endobj 2344 0 obj << /Type /Page /Contents 2345 0 R /Resources 2343 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2322 0 R /Annots [ 2323 0 R 2324 0 R 2325 0 R 2326 0 R 2327 0 R 2328 0 R 2329 0 R 2330 0 R 2331 0 R 2332 0 R 2333 0 R 2334 0 R 2335 0 R 2336 0 R 2337 0 R 2338 0 R 2339 0 R 2340 0 R 2341 0 R 2342 0 R ] >> endobj 2323 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2324 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2325 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation81) >> >> endobj 2326 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2327 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2328 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2329 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2330 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2331 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2332 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2333 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2334 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2335 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2336 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2337 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2338 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2339 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2340 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2341 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2342 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2298 0 obj << /D [2344 0 R /XYZ 28.346 0 null] >> endobj 2343 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F45 164 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2371 0 obj << /Length 1526 /Filter /FlateDecode >> stream xYIoFWLoMf_M Em4MGBIѱ}TF^; H> E[DЋ9RR A\1lDL3LB :@_NfOS(XN`bBb :9C_U~X c}t~,9y9cq-#A> /Parent 2322 0 R /Annots [ 2349 0 R 2350 0 R 2351 0 R 2352 0 R 2353 0 R 2354 0 R 2355 0 R 2356 0 R 2357 0 R 2358 0 R 2359 0 R 2360 0 R 2361 0 R 2362 0 R 2363 0 R 2364 0 R 2365 0 R 2366 0 R 2367 0 R 2368 0 R ] >> endobj 2349 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2350 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2351 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation82) >> >> endobj 2352 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2353 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2354 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2355 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2356 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2357 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2358 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2359 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2360 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2361 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2362 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2363 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2364 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2365 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2366 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2367 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2368 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2346 0 obj << /D [2370 0 R /XYZ 28.346 0 null] >> endobj 2369 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F45 164 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2395 0 obj << /Length 1527 /Filter /FlateDecode >> stream xYK6W7zh&@MEmZ66*YE}HI^z;@.4=$e>"Lޕ•Pa%ba5^9|M [b):9[g 3 5}Wll..e5ŵ2`&\i.j,6@u`!ӶoSqO~=8/ T"3 T6 Cvx[6(qA?1QKh.!mU!q]߭eU]7Q8vUź*O~ES\"%PKim*͘;~.]yѩ[MPXs~)Ď$>4taP*MvJ1@{/ۿ*,2M$3:QZwrYuÚ`t$f Uo9"g !]2wwnm!۩bVֲm.vc4 l_ G[ɋ)'KhA; 0%z#?5J< Zm9@NbC)R\?`{ 6dߢ!sɃј֯":l3miNq4t<]6۞0eHQCzB<q4$9+CG_p vÛhܻ'|8'mm xviu+яdX5Z޳Qwj9y;wEڝʝ6#QGSd%K 6> V.)mwtDUL7D$Qo Íy`=xgһj;qg H,T(#c*' ʄ2iPX"L9*)‰`i :sdfJ wo~s Y|o*ئ2Q3O/d-+"vx ~EOM8x^/ޟ+KhOG%8!% ?y@:ЫE$4˱)ϛX endstream endobj 2394 0 obj << /Type /Page /Contents 2395 0 R /Resources 2393 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2322 0 R /Annots [ 2373 0 R 2374 0 R 2375 0 R 2376 0 R 2377 0 R 2378 0 R 2379 0 R 2380 0 R 2381 0 R 2382 0 R 2383 0 R 2384 0 R 2385 0 R 2386 0 R 2387 0 R 2388 0 R 2389 0 R 2390 0 R 2391 0 R 2392 0 R ] >> endobj 2373 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation81) >> >> endobj 2374 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2375 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation83) >> >> endobj 2376 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2377 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2378 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2379 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2380 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2381 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2382 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2383 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2384 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2385 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2386 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2387 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2388 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2389 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2390 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2391 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2392 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2372 0 obj << /D [2394 0 R /XYZ 28.346 0 null] >> endobj 2393 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F45 164 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2419 0 obj << /Length 1526 /Filter /FlateDecode >> stream xYK6W7zh&@MEmZ6*YIz$@.4=$eAo&JJ(qŰ10e ]Vh9}L^Q-,`bBb :9CMպ|5 c];tzY9y5Cq-#AnX,$qٜ+=-EMWv⴮Gs*%Vڠ9Ӏno-p44&i6s̴~.:sw+K^-3:ݔ9&$`O>rCYG +#!Zai\rcr(0m;uד@%2PAeӿ P1Ime|@ ^A(ΑKbUUn*wmݥݺ\a[u%X0mQUlbد]^4Ņ/Reʱ]v6ގcUQN,Lh*W2DǚO'z`gf Eg$q}=RxlSj{Pao"IF`U&FjB =gW;g25 O%H:,Bs8 )#E"(xҴ"e~1ÉYrHh-[{Km5UU7ňcC.(Lm3r0ci]wnm!۩bV߲m.<[8=Is[[ɋeA,F_,b{¬13tuX~j̕"'z[9Έǒ (3+8@e1&Ӳ-K ش =)F?fnSOsyÈhU{-z<-C* :*ģ!c"w|ù+8^~bm<>޷ݞz۾-n 6T||siu#4dX5Z>Qj9,;w(y29:&S+VytG4e0-Q1)?xarI8t%} ]'e~ƍ(` s5(,]ky8p@ᨰ w:LC`xΔ@PS0cI.h0 7` ĵIYg< Gid`SHi9u!QIOz d`"]&g*E>E5Ε޸j FЁC#2Jr^q1w ַUϜRM|W83$IU*Kȗ1eLwX({\B, \&JUDBCM4Y FLVDJ23B|JV wo~s Y|o*ئ2Q3O/d-+"vx ~EOM8_ x^/ޟ+KhOG%8!% q8y@:ЫE$4mx endstream endobj 2418 0 obj << /Type /Page /Contents 2419 0 R /Resources 2417 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2322 0 R /Annots [ 2397 0 R 2398 0 R 2399 0 R 2400 0 R 2401 0 R 2402 0 R 2403 0 R 2404 0 R 2405 0 R 2406 0 R 2407 0 R 2408 0 R 2409 0 R 2410 0 R 2411 0 R 2412 0 R 2413 0 R 2414 0 R 2415 0 R 2416 0 R ] >> endobj 2397 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation82) >> >> endobj 2398 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2399 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation84) >> >> endobj 2400 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2401 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2402 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2403 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2404 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2405 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2406 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2407 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2408 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2409 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2410 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2411 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2412 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2413 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2414 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2415 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2416 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2396 0 obj << /D [2418 0 R /XYZ 28.346 0 null] >> endobj 2417 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F45 164 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2443 0 obj << /Length 1525 /Filter /FlateDecode >> stream xnF$4̾4hc1}Gv8<}zz1#+ qŰ10e ]6|}_NfOS(XN`bBb :9C_U~X c}t~,9y9cr-{"ŚFX.?v.ŀP{a o"IlEm0c64 1 *ԝc9kKИp9ܝʩZ=Cq5EhBʄtQ1t,[:44f1t8+>i罫P%MiqlQz죯A[*qL,P3wuCWn׎N=VSWW8}뾻ookc؃'8٤8 8b ebxZXGFt]*,w[_^oCN};`Vpu xPxƘB{~)Ц,'K,=wXqGa-pg۹Tͅj F @)ƎX‰R9*;\s)s9+H.ߢ/2j֊Wp ~f7Q'5r$3/L!wq Q"qTFcEPn借`+[kPE c +4GہzaBvc 68=O r _ E)u@ m#qgCHl'M@!7&! kD}J [5~"٫ ]8b)y粁lr&ٛ$N@>^&j_AH[A ~!Tg}NS#p"p}Ae98XL8) %5eSEIH!n7Y:Fyv*6*cѱ!&8cz2 r endstream endobj 2442 0 obj << /Type /Page /Contents 2443 0 R /Resources 2441 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2322 0 R /Annots [ 2421 0 R 2422 0 R 2423 0 R 2424 0 R 2425 0 R 2426 0 R 2427 0 R 2428 0 R 2429 0 R 2430 0 R 2431 0 R 2432 0 R 2433 0 R 2434 0 R 2435 0 R 2436 0 R 2437 0 R 2438 0 R 2439 0 R 2440 0 R ] >> endobj 2421 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation83) >> >> endobj 2422 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2423 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation85) >> >> endobj 2424 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2425 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2426 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2427 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2428 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2429 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2430 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2431 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2432 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2433 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2434 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2435 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2436 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2437 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2438 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2439 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2440 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2420 0 obj << /D [2442 0 R /XYZ 28.346 0 null] >> endobj 2441 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F45 164 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2467 0 obj << /Length 1524 /Filter /FlateDecode >> stream xnF$4̾4hc1}TFv<}zz1#+ qŰ10e ]6|?̞>Q-#3ĄĄtrMlW~YusnZ`Dy@JXQKr:i`GTJAK \l,JRcIb#ly\̷Ms枸 K ίtK:omHJAmXd` #j' +!Z€[M9fc@#J( i;q{~YI \(Ĉܠ^¤ǺCc9/A@HΉZ@?m A\훦 Qu~UBX7m%t$+M.y*Ob^tՅORiʱ1]M)}^5'Q,T"Dǚ=zg %c$i}5R\x]ס+!ŸDP`Flh@b[U;anjs֜x-1rC;a S{jP 颤$UXs%H%v%$4Pc ́ߡ9RZyUu9Z%FfC3rtKtL TLG]"nu 7DJXse8&kmud85 (cj 5GNk2Dp.dяXr@~}S+V(T;4x[/]#Gb0SrZ%}]Ge?V&P ZkPE c +4GہzaBnwc 68= r _ E)u@ m#qg4CHlw'M@!7&!b%">'KEN? Zz.L1єļs@|6 9MLGr' sqہ /5/W wÍq(g}]!_eH?Y]n{AL J>DY@SIYP&ϔqwOpH|a2Cҩ"qH$ 7"hJP4H:k YSj|Vh1 ~+}u6?y0ph-O+q8:x ۝0stN˥ۓ7 Jdpb>7Y:Fyv*6*cѱ!&8cz2 rۿZd endstream endobj 2466 0 obj << /Type /Page /Contents 2467 0 R /Resources 2465 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2468 0 R /Annots [ 2445 0 R 2446 0 R 2447 0 R 2448 0 R 2449 0 R 2450 0 R 2451 0 R 2452 0 R 2453 0 R 2454 0 R 2455 0 R 2456 0 R 2457 0 R 2458 0 R 2459 0 R 2460 0 R 2461 0 R 2462 0 R 2463 0 R 2464 0 R ] >> endobj 2445 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation84) >> >> endobj 2446 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2447 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2448 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2449 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2450 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2451 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2452 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2453 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2454 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2455 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2456 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2457 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2458 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2459 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2460 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2461 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2462 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2463 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2464 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2444 0 obj << /D [2466 0 R /XYZ 28.346 0 null] >> endobj 2465 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F45 164 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2491 0 obj << /Length 1521 /Filter /FlateDecode >> stream xKo6_lf~aZsEIV; )ɡ$Z?}' DЛ Y)֏!+ i)SBt2yD Rtr3fc.W\;]lӫjۗk te,bMF͹-j,6u=S)͙6PrFNJagL+b3Ľ`X:zFr6]猤ɆeN6`1:Catx0BY0c+;;e1@w9iĎ]{~YI \(Ĉܠ_¤DzA c>^@HΑMbVUخ*m݅ݪ\a]u)h0mXW6߸)?mx>I )Rt1hu۬z3ƎiƧڼĭ|Gގrɹ/BTq9=qzfP4FL GG:[(K&ۥpk/[2,"I$ɱ5) ftȆ$FZ{.wΪ94f 0w',rnP\j#2"]4|(MkKR,J:heB UMt*ݛ0P{ uQzWT8&Fff( }}Pienh*M7}˶ޮ5p1I,N6*N}B$+XB}ZzO GEWn1Wt[ЛvcȩoG/ aG@l4Khiӧg(Dt wDJb_s{Iܫ?>o;}1` C naT]r8C͞S/aDX(5Z>RUFs8 ro\\~ ʠN>WhğZ[h?-t nuL s]mܧHHuw&"(7rO`Z ,58KX9@}*t#Ґ0vqk,g^NC.ns e&B ?{9y%)}!\gwFl%*EerqL%Ap>SN-J#K!!2A(܉&+A(#ˤE$5#[h-oQ_c.@C%WvmzQ/,~%Z2ґW[e,/;~&HwR/joO(ꓨ‘youMy:ЪE$ˡ!J endstream endobj 2490 0 obj << /Type /Page /Contents 2491 0 R /Resources 2489 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2468 0 R /Annots [ 2469 0 R 2470 0 R 2471 0 R 2472 0 R 2473 0 R 2474 0 R 2475 0 R 2476 0 R 2477 0 R 2478 0 R 2479 0 R 2480 0 R 2481 0 R 2482 0 R 2483 0 R 2484 0 R 2485 0 R 2486 0 R 2487 0 R 2488 0 R ] >> endobj 2469 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation85) >> >> endobj 2470 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2471 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2472 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation79) >> >> endobj 2473 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation80) >> >> endobj 2474 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2475 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2476 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2477 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2478 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2479 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2480 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2481 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2482 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2483 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2484 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2485 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2486 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2487 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2488 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2347 0 obj << /D [2490 0 R /XYZ 28.346 0 null] >> endobj 2489 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F39 78 0 R /F16 42 0 R /F36 1316 0 R /F40 605 0 R /F45 164 0 R /F21 79 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2514 0 obj << /Length 1492 /Filter /FlateDecode >> stream xXIs6WVyZؗC͙2֒bIO}b!Mmq,7uLJ$f@:+zbpf2ct=8l Gz7>U%ĚP9IS[ 5L>1k8.Ab-T iVZOooO*pXݕqU/t~h:\?:P4&I?N@N"<qaVaeq2d:qfa4Zޠ@fsbAz6C67 {nD(WJ+(, b-a+M=Cn]aLPXYn֡+!" L=2㐎_@s~ya<#LA0;G;4GQ/ZU9jAvL4f\B`mLL:.݂=U@9>P?Ɂ!X:jX 뚾 Gl3W~Ok k+ojHnN;[ć(p"!֍-w#Qɤ#%"LaT0~"W#liLg.φ3(7%9ZHqY n^X~}/g}]qү2Ouv(vR / *Kȗ1z4Lp>S"8_"L*x«7(Fu>E$5Ghd.oQ1 x{2Y| 2]Ǩ׉ykݵS:ʊ]R<"`y&ܑT \=&HQ;*ghn=YJ- 1md XNr endstream endobj 2513 0 obj << /Type /Page /Contents 2514 0 R /Resources 2512 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2468 0 R /Annots [ 2492 0 R 2493 0 R 2494 0 R 2495 0 R 2496 0 R 2497 0 R 2498 0 R 2499 0 R 2500 0 R 2501 0 R 2502 0 R 2503 0 R 2504 0 R 2505 0 R 2506 0 R 2507 0 R 2508 0 R 2509 0 R 2510 0 R 2511 0 R ] >> endobj 2492 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2493 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2494 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation88) >> >> endobj 2495 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2496 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2497 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2498 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2499 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2500 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2501 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2502 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2503 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2504 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2505 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2506 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2507 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2508 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2509 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2510 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2511 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2348 0 obj << /D [2513 0 R /XYZ 28.346 0 null] >> endobj 2512 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F39 78 0 R /F16 42 0 R /F18 43 0 R /F45 164 0 R /F28 2515 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2541 0 obj << /Length 1496 /Filter /FlateDecode >> stream xYISFW-5/T*Sm&Gcl)EB^dpKO~{]! HgRXoBW . Sr.6=vbp|-[b)Dc.8b‘$> /x|BU(&PFf;,v]V]#?, ?W={7b%bb` nР͍`pϭ@ Xk [k3vޤvmuq^B=EC)VBEj%ř{d!!>+j 6>쬕xyKCa/Iwv8h<σZNׂ8!* i̔ R9 ژXu`G"zrl}4 ϙÁ !X:jX > G lSW~Ok ]k+kj9bfp?K\ ǣzp<_/bQY,dJU_0Teob0(rk緘r7]Oz ,OOϓ`~;I^Z}"V!P.WTv҃L&=f`jS3=!E LK) z'P'Ĥ-وioz S띛`Gnofc,S^^cfp+[:Fó}@m[:o{ϱO#N| ie7b*mx|ݶ%}]HK?u0 i,ImfULJh >rD}#ho>'"@qq7_-i[8KWҧb;vX{H;W)C14*Kȗ1y2lUrB } 0Dp(q>R' Zu<#IHIbFhpz`(s_,A>Cr D> /Parent 2468 0 R /Annots [ 2519 0 R 2520 0 R 2521 0 R 2522 0 R 2523 0 R 2524 0 R 2525 0 R 2526 0 R 2527 0 R 2528 0 R 2529 0 R 2530 0 R 2531 0 R 2532 0 R 2533 0 R 2534 0 R 2535 0 R 2536 0 R 2537 0 R 2538 0 R ] >> endobj 2519 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2520 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2521 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2522 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2523 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2524 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2525 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2526 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2527 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2528 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2529 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2530 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2531 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2532 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2533 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2534 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2535 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2536 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2537 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2538 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2516 0 obj << /D [2540 0 R /XYZ 28.346 0 null] >> endobj 2539 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F39 78 0 R /F16 42 0 R /F18 43 0 R /F45 164 0 R /F28 2515 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2564 0 obj << /Length 1494 /Filter /FlateDecode >> stream xYIw6WV/nkn^nI*#[j-)@,ű-'q`07C+DЛV Pa%baZަ] OE`K,EpGL8DлoO*%քHf aXc w_l mL˰Rzz}}Tqjp=z1_Φ@[z D*16H5q r2ĮA}] ,dN'N&vu3 &O*o 8{ d6(!g4hs0Htru$X)׺gI{/8>) 4 S:b%[6PRIG}`hZ97L{>td)vhGâuZn TIPHcLU Ī-8[cU|C@Q h`jj2ʲg80W~O㵄ڊ1O=R{Anc1B45as "l[PɀP>9bfp?K\ ǣzp<_/?墲XTثd4X`rk緘$n ,OOOS`~)w^Ͻ>ame ~ 'is@bғNW7dgqJ`SCZ .JfR\L]Ы<ဪ8!mF (%xkteZ;rf&=R{=ثKLì#+\b3sKhxY:FۖsF>'݉=Z Q˗ZL^ / :@m)_0}O|mHz}gϬgId4VWhoӗ8V8_(0DBH,70'9􆜰4;Y4^FRp(17s@nݸFʵ(g ם֠Hrky8rρip(ʍAݎ 0D(sh @46=Q.)#H|,?]{t>uL:@_"1&XF HH]M1)Qeِs&s$7Rm@ø/V釭qY_Wr8 c|FNUh es$qL%~L8)xad`PBt_/ \&J*x+ 7(Zux_'-"%E3F$'w~r[+(W:FNS_s5쵤QVЭ:5x&;z}nIUnϥۓnaIQx6jǛ) h.bUd)$gh endstream endobj 2563 0 obj << /Type /Page /Contents 2564 0 R /Resources 2562 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2468 0 R /Annots [ 2542 0 R 2543 0 R 2544 0 R 2545 0 R 2546 0 R 2547 0 R 2548 0 R 2549 0 R 2550 0 R 2551 0 R 2552 0 R 2553 0 R 2554 0 R 2555 0 R 2556 0 R 2557 0 R 2558 0 R 2559 0 R 2560 0 R 2561 0 R ] >> endobj 2542 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation88) >> >> endobj 2543 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2544 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2545 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation86) >> >> endobj 2546 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation87) >> >> endobj 2547 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2548 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2549 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2550 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2551 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2552 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2553 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2554 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2555 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2556 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2557 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2558 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2559 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2560 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2561 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2517 0 obj << /D [2563 0 R /XYZ 28.346 0 null] >> endobj 2562 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F39 78 0 R /F16 42 0 R /F18 43 0 R /F45 164 0 R /F28 2515 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2587 0 obj << /Length 1852 /Filter /FlateDecode >> stream xZKs7 W.CMgzh&Mط>fyÑu__\rwv8@>t9%ck#8~D #Bsj"p \eI{B_= 9 cTCOȯgBh3/*Շ2RVYH7%TXRpCQɫYeNYb60ʙA`幅>LQLBUl)Ӑ8S@25#ǷJcbyY6r Y7{?y;&pjN8gTYAFdNֵpV d I3i@>p(Oe4#^cQ&ި/k=$Ij)֜l},', eLyє:cx͔xB!Ľ.S41}e%+4'gnqՊֲE;u Jb7Ҧ%ڙ&ñm \vtit`eAE)\R.Ef>Z-Eɐ 2)c,Ug!4iq$덟NvgBN =3=UA`c6v_:b)Gr] a΁D @bn$LQn yB6 iS im0A_4Rn<*! X>5:mnPņhYVy0NWeZ-`~|դ/apHzS.Z=cFSn>pKX^qM9Uʼ\Ơ\,'UU#=r8/NwҞa5O;|'&YKwgͪmT+>:LG!!rY E -~ oͰĊKV`0*l#𕔠snlUG|\LӲ&,Ϊl_$R-Fx_pBsAO9G 썢fقk7E5KOJap:>tcjpӭy8k)ztkmG#OpR=[TݍحˁsKNFu<p͕Zߣs n20FXNQfv"d![1+f/ ®"-`.{+\8¨{ 7xp_UU.|ZoQ^Tu=rY_4i<7,ij9)k-g؋*F Եw4A̰=XA :r1tU_' sDfi?19F  G#Qs?1307s#je xYw] X:K1okܤGekFܵtJ ]F‘ X(nG=mʻH2K%3)> /Parent 2468 0 R /Annots [ 2565 0 R 2566 0 R 2567 0 R 2568 0 R 2569 0 R 2570 0 R 2571 0 R 2572 0 R 2573 0 R 2574 0 R 2575 0 R 2576 0 R 2577 0 R 2578 0 R 2579 0 R 2580 0 R 2581 0 R 2582 0 R 2583 0 R 2584 0 R ] >> endobj 2565 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2566 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2567 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation91) >> >> endobj 2568 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2569 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2570 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2571 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2572 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2573 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2574 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2575 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2576 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2577 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2578 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2579 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2580 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2581 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2582 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2583 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2584 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2518 0 obj << /D [2586 0 R /XYZ 28.346 0 null] >> endobj 2585 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F24 1317 0 R /F40 605 0 R /F45 164 0 R /F15 2588 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2614 0 obj << /Length 1855 /Filter /FlateDecode >> stream xZYo7~`"M}h&hP8[@׎Z%Jdljp8!F#oXgǏHaDhNPNk,ڤ/KQSTCOȯgf0_AEF"&o?~KNPaɐʜB^-8dg]s;X敢VڔWT;Sg8x˖,M9bX~q0ixѧ KTAe3A C#dHvŔ1Llm4~cOP';ZPQoeF4׻.Q+WC,e-hPn $ QYH$V@Jo'oZP/I-@@2rSaTNAp D}ztݢ Ѳ(/`4]-dhd,THbU0"qNN}'.0l^V\`4嶪_~3M,t0YE͋etrRTsCMϦ" P.8>tcjpӭzkztö@]MlHleqZgq:=-G9?Dqes{0Q_F)Vb>f!Vk38: _* r#&[ӱU*j;67x_eY,l-,ZF+Oʪ힗Y.W~Zrc|k[4ҋysnj`Ut-ʈ{2-0WJ, rUl8za.G#4=S]]M G=X¹hUN/030sqCG2~U@ W6 -ʻz't*b޴;ܤGdc)kЕP#`,Q܎{&/<ZwMe~9Kf(Sx$pH uZ(ИnW-n9~(Bjq؅xEӰ=G-$$R?#PɋEY"$"=$эi1Dbҟ%CXDz.M)Ig PL7 m[$ֺ!ſXf-5rR,CzWg_n]#{y&jͰ)Ǎ1@xhYFB0 2?3- zcXsNnmsҷzw\!ݤ_t zLJI$6 )h.M24 ΤJ;v endstream endobj 2613 0 obj << /Type /Page /Contents 2614 0 R /Resources 2612 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2615 0 R /Annots [ 2592 0 R 2593 0 R 2594 0 R 2595 0 R 2596 0 R 2597 0 R 2598 0 R 2599 0 R 2600 0 R 2601 0 R 2602 0 R 2603 0 R 2604 0 R 2605 0 R 2606 0 R 2607 0 R 2608 0 R 2609 0 R 2610 0 R 2611 0 R ] >> endobj 2592 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2593 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2594 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation92) >> >> endobj 2595 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2596 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2597 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2598 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2599 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2600 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2601 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2602 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2603 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2604 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2605 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2606 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2607 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2608 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2609 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2610 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2611 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2589 0 obj << /D [2613 0 R /XYZ 28.346 0 null] >> endobj 2612 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F24 1317 0 R /F40 605 0 R /F45 164 0 R /F15 2588 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2639 0 obj << /Length 1858 /Filter /FlateDecode >> stream xZYo7~`"M}h&hP8[@׎Z%Jdljp8!F#oXgǏHaDhNPNk,ڤ/KQSTCOȯgf0_AEF"&o?~KNPaɐʜB^-8dg]s;XƕVWT;SG8x˖,M1b~q0ixѧ KTAe3A C#dHv!clYФ~:ւ 7̈z4}j= CT;}/@0Eہ 曀 $f@Rm 0A_4 xUt,Qt^&xsbC,ʋ:GajQ f(ZsK7=0Qen>c<[U/r2W pI)cX^|R J]upyn/P zP-hݹꃿpUb!.Xn~l؝r!Tnc`C[-?+JneDb|, :[Mg!p^W zQ~y2(3[2r %YDW?ΰUlǞ50U^EuU|Ye<賊DB2yYꊦO=G?hM#IQI9G_ VeqNׂ7!^maY2-0WlJL rUl8㘺0]UVlhO4b̂ÑBgT,ߪOE :Q_|3PX:f~~u$|7Zl>}Z] KjT5(g" r,TiIPP̅~6x49}L|/ʔU$ =-2V0 Y&HEd5ɇ,Z-s;Be$d>!s8SpgX8ƹ5t$ts{ > /Parent 2615 0 R /Annots [ 2617 0 R 2618 0 R 2619 0 R 2620 0 R 2621 0 R 2622 0 R 2623 0 R 2624 0 R 2625 0 R 2626 0 R 2627 0 R 2628 0 R 2629 0 R 2630 0 R 2631 0 R 2632 0 R 2633 0 R 2634 0 R 2635 0 R 2636 0 R ] >> endobj 2617 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation91) >> >> endobj 2618 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2619 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation93) >> >> endobj 2620 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2621 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2622 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2623 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2624 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2625 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2626 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2627 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2628 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2629 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2630 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2631 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2632 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2633 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2634 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2635 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2636 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2616 0 obj << /D [2638 0 R /XYZ 28.346 0 null] >> endobj 2637 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F24 1317 0 R /F40 605 0 R /F45 164 0 R /F15 2588 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2663 0 obj << /Length 1855 /Filter /FlateDecode >> stream xZYo7~`"M}h&hP8[@WZ%J'Npot9%cp?"9Bn8ɪ ÍI_= 9 TCOȯgfXAEG"o?~KNPaɐʜB^-8dg=?*JF93bXzn!/(I&\sBU+R!q|'*Peԫ5F&o{޳l:r Y7{?y=pjN8gTYAdN]8#dCI3i@p8xN̏y3kjAxXˍCZظ(kɺKyR>QƔWQgO;7-f*Q!C x66i6l-j %(hk0T jOVq6մ/85)h!%KSsftL^%R>UPp'Pk!aAb&[{g!4ip$뵟NvrM;3UA`c5z_b)km@ŝ ѻHR@R{m@R s@Rm0A_4 xUt,Qt^6xs7bC*"vD}f뢅 i0>P v@>k0YB$n:GarQ QkECBH x<lpkFF%ͺ1).|>&j7x{X-gYQgt>$RF":/zwՁ j~sSKX۩j$xQ D^6X3' :pmqsRK-V_ )H{Zd)@`,M,YDj&[YN#[RwB a'd~N^g ,PT8ױfNnns[]}G늞s?K7,a]0a?^,>yvR8 ֔ 4YFyp]e.hnFc;?I- endstream endobj 2662 0 obj << /Type /Page /Contents 2663 0 R /Resources 2661 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2615 0 R /Annots [ 2641 0 R 2642 0 R 2643 0 R 2644 0 R 2645 0 R 2646 0 R 2647 0 R 2648 0 R 2649 0 R 2650 0 R 2651 0 R 2652 0 R 2653 0 R 2654 0 R 2655 0 R 2656 0 R 2657 0 R 2658 0 R 2659 0 R 2660 0 R ] >> endobj 2641 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation92) >> >> endobj 2642 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2643 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2644 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2645 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2646 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2647 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2648 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2649 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2650 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2651 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2652 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2653 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2654 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2655 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2656 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2657 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2658 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2659 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2660 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2640 0 obj << /D [2662 0 R /XYZ 28.346 0 null] >> endobj 2661 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F24 1317 0 R /F40 605 0 R /F45 164 0 R /F15 2588 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2686 0 obj << /Length 1853 /Filter /FlateDecode >> stream xZYo7~`"M}h&hP8[@׎Z%J%Npot9#cp?"9Bn8ɲ {kn:<{,Fs@O pWRe 9>!~*B|Q=(?͊DϾ-:A%Cn(s6 y?+㜓En*a̠ab鹅?LN4^ɖ2 >!TJ,^12q|+$<&e c4_߽x0Vs9 2}${mvҕYE.II$KJ*I é,^3g~soLW Zn֢@~PEYcM]2r2:cxŔx!ؽi6ST1}eIamQV()FAc^R@Tt`WZiS\MSSLᘂ6k.[4u:!`fAE*\R.E>S }2 &k0!d.ag{BoL^ d'[ *[3#]VӨ!hPn $ QY;H̭)*$O7$^ 1 $۶ ZEPMQ:@Q-EnIl7w.6DˢXcGttUR! gM& WčG;9FBO{Yqє*~oX6=8e붉rWvd-7/.pIYHO欘abýp@#: gk\͸ x@~ݝM].GWX:f~~u$hH?,|KX۩j$xQ D^X3' =pmqsRK-À*SRW$8SZ$d X[Z#L"ֶ2&z{Gh1 EPg ´O>Y0;qc*d% ϳҷ`=~7iº`~KX&%}p^o )h.wś\܈hw&8; endstream endobj 2685 0 obj << /Type /Page /Contents 2686 0 R /Resources 2684 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2615 0 R /Annots [ 2664 0 R 2665 0 R 2666 0 R 2667 0 R 2668 0 R 2669 0 R 2670 0 R 2671 0 R 2672 0 R 2673 0 R 2674 0 R 2675 0 R 2676 0 R 2677 0 R 2678 0 R 2679 0 R 2680 0 R 2681 0 R 2682 0 R 2683 0 R ] >> endobj 2664 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation93) >> >> endobj 2665 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2666 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2667 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation89) >> >> endobj 2668 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation90) >> >> endobj 2669 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2670 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2671 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2672 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2673 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2674 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2675 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2676 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2677 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2678 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2679 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2680 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2681 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2682 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2683 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2590 0 obj << /D [2685 0 R /XYZ 28.346 0 null] >> endobj 2684 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F24 1317 0 R /F40 605 0 R /F45 164 0 R /F15 2588 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2710 0 obj << /Length 702 /Filter /FlateDecode >> stream xWKs1 1=ĕ:tCIn $ ! ٻi:,'{"\I{X U4tЊ W-E T ràLԠS#,Gfa+j?sZrwf󞇟ݛ%K!QA{~5DOeJިs0![P>#l/`pRdUe(CwdȤ7de1<R@|c@˽[@w'!k'Bs ٔR GʈQa;Um~ BG1:MbY!<]+J\;"-)F,Kz1J!C/U4jQy,-7l_"wl<(4 z?:aT.YK%Y|eUMa+%HM XvC3R֑H>I2x-}^d-ǒy?@d[|2&6sךCh*$H_~T#Ք'*k,iJpY)3įHE('$Tcz_ v˞}Noi%v_/x]'s/nzvyIE.ROUb|$,[ImCꇦOUiUՊā/\Av endstream endobj 2709 0 obj << /Type /Page /Contents 2710 0 R /Resources 2708 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2615 0 R /Annots [ 2688 0 R 2689 0 R 2690 0 R 2691 0 R 2692 0 R 2693 0 R 2694 0 R 2695 0 R 2696 0 R 2697 0 R 2698 0 R 2699 0 R 2700 0 R 2701 0 R 2702 0 R 2703 0 R 2704 0 R 2705 0 R 2706 0 R 2707 0 R ] >> endobj 2687 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/hash1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2711 0 R /BBox [63.8 351.8 400.2 576.2] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 2713 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2714 0 R /Pat96 2715 0 R >>>> /Length 1301 /Filter /FlateDecode >> stream xWMo7 Эvk a;ڱ[3ڙ69-/艤Hڙ7Gl0o|ؐ/&7Poػ~somb'?dl/6z2$_wͼ*7~h'ssn.ѺB/Wy6\2`na}}c=ypmpë57o6M7zG pwkNr\Su87yw-B:4 pB,ÉM'7͂:r\zٍJEc9BwPa} ka(—(Hqf|_=4(u\nRnSt}u3|,hqpnN_VE D=r)GR%'ޕ7#*C )jTͣփ Mu.A!΢Uo!ZLđLl$.ņ+eos89ye.d,$A\+Yʄ9]8}+h`b cvj[|em 7"SĖ/ag 1L2Z!,+\SǬmG2g[4$ka 6`fQ9]ЩV6yqlSAeKPD-$j]h&5B&84йR);ő:0ۊ(ZnWXvV1'֐OC Gzq=x8EVPR,窬v~禚ǥU[gǝ@#\88RGP#rhT7͂:4 pb,M5fb*Fc5A ^*W~~9a+vu'3W{~Yqk6 ۇg6\_ z-eRq/i:6,3lÂ8f36-,QogiZfԻ'8sE\Reݪ)lm'*ױ\/RyT-O(^v:'l`GBElЄSvNir4iDBzrA[8`x{6a#U޹@>fTh>,VЉeb99D$0"]?آ18zɟ?wevV,mV>H<Mc>YE~fw:ym΄Ɣ.]F-ǓKidb֧w^tə`vG'|zVf+F񌿰ҏK*oWݣLQȯ6!WE,Cce} "K |B endstream endobj 2711 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212170456) >> endobj 2713 0 obj << /Type /Font /Subtype /Type1 /FirstChar 39 /LastChar 121 /Widths [ 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7 461.1 683.3 461.1 461.1] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 2712 0 R >> endobj 2714 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2715 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2712 0 obj << /Type /Encoding /Differences [39/quoteright 68/D 80/P 97/a/b/c 101/e/f/g/h/i 108/l/m/n/o/p 114/r/s/t/u/v 121/y] >> endobj 2688 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2689 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2690 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation96) >> >> endobj 2691 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation94) >> >> endobj 2692 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2693 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2694 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation96) >> >> endobj 2695 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2696 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2697 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2698 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2699 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2700 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2701 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2702 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2703 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2704 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2705 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2706 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2707 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2591 0 obj << /D [2709 0 R /XYZ 28.346 0 null] >> endobj 2708 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im35 2687 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2740 0 obj << /Length 718 /Filter /FlateDecode >> stream xWKo1W19ĝ~\PQ PҴT ;6ZJEisY7AHbI,1`V4V.a9:cXf>:yOUH0_Bpʑm:+|/&ǻz}Lsb[J~lw?f!mq^ݜJ蠌uYT])R$`jMY?sE1rG3tX?èQE { l k)/EojꚑzG4ᗇmbJ*Z4,$tdܾt塿 Zy endstream endobj 2739 0 obj << /Type /Page /Contents 2740 0 R /Resources 2738 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2615 0 R /Annots [ 2718 0 R 2719 0 R 2720 0 R 2721 0 R 2722 0 R 2723 0 R 2724 0 R 2725 0 R 2726 0 R 2727 0 R 2728 0 R 2729 0 R 2730 0 R 2731 0 R 2732 0 R 2733 0 R 2734 0 R 2735 0 R 2736 0 R 2737 0 R ] >> endobj 2717 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/parcon.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2741 0 R /BBox [191.8 431.8 528.2 598.926] /Resources << /ProcSet [ /PDF /Text ] /Font << /F7 2743 0 R /F8 2745 0 R /F11 2747 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2748 0 R /Pat96 2749 0 R >>>> /Length 853 /Filter /FlateDecode >> stream xWKo@WP>f_5RS)Fik 6K^㛙ٱB_ŋPğBB'#\bV(*TXVT?eyDo'w}a8ahd`Ζ.20#-)Qfz+©ޤS$#  hLNhث{a1V 0t]:r0V#i=nVQngBxcNM5&NiK-k!us3-l>F*ƍ$[ݻe$1Zg׫iU aّ!c=Z Qf>)Քb~kimFܒ(΄CDMc_ܵt^㮅;qT |gygH۫g,B$T.֔CQUOZ8VW[x*w۾W^)}(mh ;;r9u\6f~n7D-FǧgɔG-$y|$ ] $zaKuB#lI Br{qd\p 2L{%dĦIp D4jFǟR StCrvφ endstream endobj 2741 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130208173232) /ModDate (D:20130213191737) >> endobj 2743 0 obj << /Type /Font /Subtype /Type1 /FirstChar 49 /LastChar 53 /Widths [ 569.5 569.5 569.5 569.5 569.5] /FontDescriptor 167 0 R /BaseFont 181 0 R /Encoding 2742 0 R >> endobj 2745 0 obj << /Type /Font /Subtype /Type1 /FirstChar 39 /LastChar 120 /Widths [ 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 2744 0 R >> endobj 2747 0 obj << /Type /Font /Subtype /Type1 /FirstChar 112 /LastChar 112 /Widths [ 503.1] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 2746 0 R >> endobj 2748 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2749 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2746 0 obj << /Type /Encoding /Differences [112/p] >> endobj 2744 0 obj << /Type /Encoding /Differences [39/quoteright/parenleft/parenright 44/comma 49/one/two 58/colon 65/A 80/P 97/a/b/c/d/e 103/g/h/i 109/m/n/o 114/r/s/t/u 120/x] >> endobj 2742 0 obj << /Type /Encoding /Differences [49/one/two/three/four/five] >> endobj 2718 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2719 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2720 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation97) >> >> endobj 2721 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation95) >> >> endobj 2722 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation96) >> >> endobj 2723 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation96) >> >> endobj 2724 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation97) >> >> endobj 2725 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2726 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2727 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2728 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2729 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2730 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2731 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2732 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2733 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2734 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2735 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2736 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2737 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2716 0 obj << /D [2739 0 R /XYZ 28.346 0 null] >> endobj 2738 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im36 2717 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2774 0 obj << /Length 717 /Filter /FlateDecode >> stream xWKo1W19+VVABI#{36ZJEisY7A HbI,2`V8A++1z|9*a"X\B08e,§ɷn67>Lݪz6iqʐI/&QilH 2\J.7&*Z?pv*cȦ")# Qaȫ2(F46r{E]xڷ*rx4?,(O(>q{Gd-Wҧֶy?@d]|>2&6sךCsWUK"|A2hz)9NTbȸYRwJ`].3h{,7)TYC Yߥ]E"ہ{(;M8>ŗx8]=u̵;t;/ːJ\ :h*$TkIX(d݆Mqa㪪 o&fyooE}o endstream endobj 2773 0 obj << /Type /Page /Contents 2774 0 R /Resources 2772 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2775 0 R /Annots [ 2752 0 R 2753 0 R 2754 0 R 2755 0 R 2756 0 R 2757 0 R 2758 0 R 2759 0 R 2760 0 R 2761 0 R 2762 0 R 2763 0 R 2764 0 R 2765 0 R 2766 0 R 2767 0 R 2768 0 R 2769 0 R 2770 0 R 2771 0 R ] >> endobj 2751 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/hash2.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2776 0 R /BBox [47.8 431.8 400.2 560.2] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 2778 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2779 0 R /Pat96 2780 0 R >>>> /Length 609 /Filter /FlateDecode >> stream xVMo1W̍)}HU8$l!glmTy~;x4|;PY0lfRp+6N< cPا 㨧$T8675ӛ:pV5D)8OLQ Q+SsպlnB"fz e~hPѐv?+x+|pRQq5hQF2O̭J7b5&zעj?0gMPiDrRg\ &ߦ`LuoM|I'ʼyV:"Sx[ox۠()Yfv.[<1cKC>]lHܴW/yɛe7 edɱeOc!/b);"tZ@*J ɋw)_w}b\gOՊ__ }NH1u5 58Z=Qeu66@zj < N5x -?VU? XS$бOB WkPCBաЪOQdBvU]Ay>pGxGczET-EWxF:To:4 endstream endobj 2776 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212171951) >> endobj 2778 0 obj << /Type /Font /Subtype /Type1 /FirstChar 39 /LastChar 122 /Widths [ 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7 461.1 683.3 461.1 461.1 434.7] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 2777 0 R >> endobj 2779 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2780 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2777 0 obj << /Type /Encoding /Differences [39/quoteright 49/one/two 97/a/b/c/d/e 104/h/i 108/l/m/n/o/p 114/r/s/t 118/v 121/y/z] >> endobj 2752 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation96) >> >> endobj 2753 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2754 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation98) >> >> endobj 2755 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation96) >> >> endobj 2756 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation97) >> >> endobj 2757 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation97) >> >> endobj 2758 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation98) >> >> endobj 2759 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2760 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2761 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2762 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2763 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2764 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2765 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2766 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2767 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2768 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2769 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2770 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2771 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2750 0 obj << /D [2773 0 R /XYZ 28.346 0 null] >> endobj 2772 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /XObject << /Im37 2751 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2805 0 obj << /Length 918 /Filter /FlateDecode >> stream xWK6W̭23#(zH zI996^ďT"i}RF &>Ǚoi @<FOB$h5(* }׋w>w|^=A5#UL-mwr4KUv.#f7[?v]v`V֊rBM<գ{TiAs:o̤̜ c(D%c^_F.q`9q|goXrՖ&pwɫ}lrTMv ";aZfrE׷oQ%2anmyuF!vYF6c;ozs}gMuzԊ m,8/TvOIN˳״J+ㄧFho{#WX{_q1ԯjX9+\:,Rtx Q²TpZuI-4EA:+X5~IJA Q!-! Q3KwdEkruAV > /Parent 2775 0 R /Annots [ 2783 0 R 2784 0 R 2785 0 R 2786 0 R 2787 0 R 2788 0 R 2789 0 R 2790 0 R 2791 0 R 2792 0 R 2793 0 R 2794 0 R 2795 0 R 2796 0 R 2797 0 R 2798 0 R 2799 0 R 2800 0 R 2801 0 R 2802 0 R ] >> endobj 2782 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/hash3.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2806 0 R /BBox [47.8 431.8 400.2 560.2] /Resources << /ProcSet [ /PDF /Text ] /Font << /F15 2808 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2809 0 R /Pat96 2810 0 R >>>> /Length 455 /Filter /FlateDecode >> stream xTMO#1 W"5Į V{ځYT BIHP~_l.AۀL-C "@/`͔QtY^B (QX$;R!#b%kDHgKdD9}$X駠pػyK) 3{v5frKVr^4{_!B}*BZ=51pT1ˤ1]Qr?f0kջuRpnBylTmv&PM[JME7-4 l3}Ď⸲-Gj:?Wev\ ySe}BQYh:х,$-^|g8E4*i9i=ۗq?܏^Ui:ɔzn?]0-=:+;+6*r?"GuDDCF}< ..#cMl Mqq6^ endstream endobj 2806 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20110222235611) /ModDate (D:20130212172607) >> endobj 2808 0 obj << /Type /Font /Subtype /Type1 /FirstChar 49 /LastChar 122 /Widths [ 500 500 500 500 500 500 500 500 500 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7 461.1 683.3 461.1 461.1 434.7] /FontDescriptor 132 0 R /BaseFont 137 0 R /Encoding 2807 0 R >> endobj 2809 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2810 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2807 0 obj << /Type /Encoding /Differences [49/one/two 97/a/b/c/d/e 104/h/i 108/l 110/n/o 114/r/s/t/u 121/y/z] >> endobj 2783 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation97) >> >> endobj 2784 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2785 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation99) >> >> endobj 2786 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation97) >> >> endobj 2787 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation98) >> >> endobj 2788 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation98) >> >> endobj 2789 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation99) >> >> endobj 2790 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2791 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2792 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2793 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2794 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2795 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2796 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2797 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2798 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2799 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2800 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2801 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2802 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2781 0 obj << /D [2804 0 R /XYZ 28.346 0 null] >> endobj 2803 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F24 1317 0 R >> /XObject << /Im38 2782 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2835 0 obj << /Length 1240 /Filter /FlateDecode >> stream xXKs6WV cn3iɡ큡iHƔ.lq6nNϞK+Z!Ï1A:pT󜀠 ) Ya'3:$'b(זYAɅ )s8uRFe,$e+4Qx7$pH"_x L#T0qZϙC0MS BgsԠIGp"EP>ϑШ2'P|w NP#c(F## laFs3OF137n70=J'v&jqQ Qτ? ko|ٌ3O?̈}~D^hwLY4#IPPjG.dh16i^"I%^)8FD1 ILVFɋHInFwB):;G_\~e)ˈ/]=2Q02OQ~cM+j]e:y_\kwyJ6LSv!h,?I::!AxGJ3Iƃ2EŧQ%.bP+zGIյ}=,^7@^vxÈڄYK w aqGD6s1Z3WXyt/ʽ2m0)nSW/Lr hqe Όs8ZK~\ g?.WΪMhۢ|ww2̻yXة n8ʩAM9v1.@O5_ź3Z!ӭ>vs-znL#J BG߽.53yY]~BݶQTB쯞um Dt^,(;+) 3sCIYHެ ]l]|} ˮnbfQy߷;5´ t6_u]zTk~_|,+ Wݾ^K*[j %vXos* p{9(n ;J0yp}#?G}0i c@]B6OhTWfW'KXֽm>m TDW% endstream endobj 2834 0 obj << /Type /Page /Contents 2835 0 R /Resources 2833 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2775 0 R /Annots [ 2812 0 R 2813 0 R 2814 0 R 2815 0 R 2816 0 R 2817 0 R 2818 0 R 2819 0 R 2820 0 R 2821 0 R 2822 0 R 2823 0 R 2824 0 R 2825 0 R 2826 0 R 2827 0 R 2828 0 R 2829 0 R 2830 0 R 2831 0 R 2832 0 R ] >> endobj 2812 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation98) >> >> endobj 2813 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 2814 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation100) >> >> endobj 2815 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation98) >> >> endobj 2816 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation99) >> >> endobj 2817 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation99) >> >> endobj 2818 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation100) >> >> endobj 2819 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2820 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2821 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2822 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2823 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2824 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2825 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2826 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2827 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 2828 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 2829 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 2830 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 2831 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 2832 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation1) >> >> endobj 2811 0 obj << /D [2834 0 R /XYZ 334.488 0 null] >> endobj 2836 0 obj << /D [2834 0 R /XYZ 334.488 0 null] >> endobj 2833 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm1 12 0 R /Fm5 53 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2860 0 obj << /Length 700 /Filter /FlateDecode >> stream xW;o1 WptZ A35 Cqy q KLMӠixGR:p8$.M֐9Se 4 (:)2gXˁŷ;3 Ohb–\Lz89E8#@]Uuͩ-^ÒSG)x8huu>ۜW̖3l.az(앻 70<0=^r%LL3T8rr,+icXCz̕M^8X:Fv;* 'n{lcQ]hJrEr}EK&3̐gI"-y"y%2D1(EZ'Z(Oe zty;$Rfʷ*KSTZV׌Ng8^d=4X'OoGz[[Jo-ֿ[zj}fɺ1"E9 " #`R>6 [zбB|aDOM%0Q㱱PTR-G4(TYC0ʆl!r$T]9m)o[tr#Do{.7/!)!ոj>mЃ5H4k%{JD#C|~yئHVvUӢy"y*ɴYv endstream endobj 2859 0 obj << /Type /Page /Contents 2860 0 R /Resources 2858 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2775 0 R /Annots [ 2838 0 R 2839 0 R 2840 0 R 2841 0 R 2842 0 R 2843 0 R 2844 0 R 2845 0 R 2846 0 R 2847 0 R 2848 0 R 2849 0 R 2850 0 R 2851 0 R 2852 0 R 2853 0 R 2854 0 R 2855 0 R 2856 0 R 2857 0 R ] >> endobj 2838 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation99) >> >> endobj 2839 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2840 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation101) >> >> endobj 2841 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation99) >> >> endobj 2842 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation100) >> >> endobj 2843 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation100) >> >> endobj 2844 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation101) >> >> endobj 2845 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2846 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2847 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2848 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2849 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2850 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2851 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2852 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2853 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2854 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2855 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2856 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2857 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2837 0 obj << /D [2859 0 R /XYZ 28.346 0 null] >> endobj 2858 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2884 0 obj << /Length 1169 /Filter /FlateDecode >> stream xXKo8W(Kyܢhiw,BHdIRIZ`/f8ofH]".Ja^ .VMY#\X{cg(e9&Z9_jy3ĩˤY}u$= X U:κ:z>819J)ǙΫsyRM&M\$@:TXvIH7껥 ^Bd+L:a_:JrM7PwSo(\@J` T4!zY4(J^9i(upS,H7Mj[:0] nmb@ljO`ۮ| ž҃wc6&G=ve[C(p5g,;|i:C2=sp<|wNpoFd]|rxu]4Iv/HfkS  >u;6?Ƴe_y5m}v^6ɝtj? W*܉ýqy@7(f> wwsmzp:cCcwa*,&1-S5gZ)hʏr1BG)_#_o}%nn_ h@ ,UnQQIuN(☫sM. ->-%w=!W#Xh O,k 8;D%UCgAhb{J iN‹k;9Z%`Op|ON!QRX["'F-VpZ`Q#` N&w0 <@iG>X?7S*ʧ7톩gB,Os+,\%}_;%V^íDM.*M61͈eʄL*$'G D%g^B"r(V-դ34tf0 )M3f ag B^Ddf9] x-@W-l dz] 6/6qm JKR6HL"+C͍ĉMq|6YyVQQ/7,>,$d endstream endobj 2883 0 obj << /Type /Page /Contents 2884 0 R /Resources 2882 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2775 0 R /Annots [ 2862 0 R 2863 0 R 2864 0 R 2865 0 R 2866 0 R 2867 0 R 2868 0 R 2869 0 R 2870 0 R 2871 0 R 2872 0 R 2873 0 R 2874 0 R 2875 0 R 2876 0 R 2877 0 R 2878 0 R 2879 0 R 2880 0 R 2881 0 R ] >> endobj 2862 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation100) >> >> endobj 2863 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2864 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation102) >> >> endobj 2865 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation100) >> >> endobj 2866 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation101) >> >> endobj 2867 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation104) >> >> endobj 2868 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2869 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2870 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2871 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2872 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2873 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2874 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2875 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2876 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2877 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2878 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2879 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2880 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2881 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2861 0 obj << /D [2883 0 R /XYZ 28.346 0 null] >> endobj 2882 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2910 0 obj << /Length 1173 /Filter /FlateDecode >> stream xXK6W(%vjT!J&Qĸ4\q%|Ȥ-+KN~/D,{_6e;^g3UZ u0z{ΛQ'N]&M>՝(8c1T]8yub}|p))bqB;I54sl;#ѷ~X5c=&n;ӊ$i,+_i6K?jxDThvG~ ww{zpcCcaP^N_Il|V4rIBG)__/}$nf7hH ,UnQQItF(☫sOMᶂW--%=!W#Xh ,k 8;D%UCgAhb{J iON»k;9Z%`Op|Oα!QRX["'F-VpZaQ#` N&70 ,@iG>X?6S*ʧ7톩gB,Os+,\%(>Xgs57.))K`}F85AVJb44%ھ)3$c.FNxU NȡXq"hWN!#E"pbģT vր+4͘)P%Nf wz9v.ӵ]Mt,v/x ۼtٷ&K*-I_|"19OSJ43'4:dYE):OD90Lܰ<_Z1 endstream endobj 2909 0 obj << /Type /Page /Contents 2910 0 R /Resources 2908 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2775 0 R /Annots [ 2888 0 R 2889 0 R 2890 0 R 2891 0 R 2892 0 R 2893 0 R 2894 0 R 2895 0 R 2896 0 R 2897 0 R 2898 0 R 2899 0 R 2900 0 R 2901 0 R 2902 0 R 2903 0 R 2904 0 R 2905 0 R 2906 0 R 2907 0 R ] >> endobj 2888 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation101) >> >> endobj 2889 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2890 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation103) >> >> endobj 2891 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation100) >> >> endobj 2892 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation101) >> >> endobj 2893 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation104) >> >> endobj 2894 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2895 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2896 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2897 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2898 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2899 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2900 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2901 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2902 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2903 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2904 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2905 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2906 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2907 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2885 0 obj << /D [2909 0 R /XYZ 28.346 0 null] >> endobj 2908 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2934 0 obj << /Length 1175 /Filter /FlateDecode >> stream xXIo8W(&[]IҵSV>iKƛjxKX:GBq[?Xr8ύ&cnԡ&4sc8+oU;ᬺזOko}gd7^ 'e1=l.]U73e I,j2K<ͦŠs.=}`Q Hj3 [7/h@ "Un1QIhXtF(☫s!M΃-+%%wOɁ?V#Xh Ϛ< c4$;D%UVBgAinr{jF4/NkS;9Z@$`POp|ON cNLaI,EN '[8!FLgG0̾aSef!+⑏ T iτzYS ^t@b&vqPY8|'kmg~-Xoo[#'+%G1\THmcm˔ T1(NHo0/FIxUaQBD&B!F1 iJ)>[ocE=K"MCz%Pv.[Mt<v/x kӅm^lc&LH*ڸ4,B>:$O%NxD'hSW2q?z`}> endstream endobj 2933 0 obj << /Type /Page /Contents 2934 0 R /Resources 2932 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2935 0 R /Annots [ 2912 0 R 2913 0 R 2914 0 R 2915 0 R 2916 0 R 2917 0 R 2918 0 R 2919 0 R 2920 0 R 2921 0 R 2922 0 R 2923 0 R 2924 0 R 2925 0 R 2926 0 R 2927 0 R 2928 0 R 2929 0 R 2930 0 R 2931 0 R ] >> endobj 2912 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation102) >> >> endobj 2913 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2914 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation104) >> >> endobj 2915 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation100) >> >> endobj 2916 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation101) >> >> endobj 2917 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation104) >> >> endobj 2918 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2919 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2920 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2921 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2922 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2923 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2924 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2925 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2926 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2927 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2928 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2929 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2930 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2931 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2911 0 obj << /D [2933 0 R /XYZ 28.346 0 null] >> endobj 2932 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2958 0 obj << /Length 1169 /Filter /FlateDecode >> stream xXIo8W(&<Πh3YcZYj?n=b DZHa .VdҖM%IڍؗNj,},^X{:Kъeh|;x[Kͨ.&I]{uHnX_n= Ey/E2VTh9<&&z.mV /f]VR/WBɻ+L:a_:L%e& (֩@E3B0aiEj8!Q,H5n |lնtw)s*(LkɦVTR| 귾eo^ﻱkWJ7}}˶PQjoٺ 9ɾ}ݿ5{S`ޘf̋C׵,ov%IN[ym~X,}o1/aq7} m,cy4/|7xvW6ᨥɝ[yzj߬W@- ٽ}Zs1}3Nx;| ¢&껰vU^ys&1-ýI,4 +>W=}`Q UO͝wkx NkdTfV38*sJS9ŶFFK pC 8'0 z qԀ%8(@[!*])µV2&|q$6SE˰@F c惧|Rv fJ:3%9& ok aWd~?a5 ,06> Q_X=N(J0ޘ@nL7; @}nL' -mbπϪ'yR~)$_[ﷷíDM.*M6☦D5eL*$'GKO#^B'ED(V-դS4"Ff0 )5T5zbg BiX/"Y$tj2`ḷx_X.l"`Ӎ{n7a\Ri'N&g Dp0>D3#;!6O&+6*Jy"5c K endstream endobj 2957 0 obj << /Type /Page /Contents 2958 0 R /Resources 2956 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2935 0 R /Annots [ 2936 0 R 2937 0 R 2938 0 R 2939 0 R 2940 0 R 2941 0 R 2942 0 R 2943 0 R 2944 0 R 2945 0 R 2946 0 R 2947 0 R 2948 0 R 2949 0 R 2950 0 R 2951 0 R 2952 0 R 2953 0 R 2954 0 R 2955 0 R ] >> endobj 2936 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation103) >> >> endobj 2937 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2938 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2939 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation100) >> >> endobj 2940 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation101) >> >> endobj 2941 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation104) >> >> endobj 2942 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2943 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2944 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2945 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2946 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2947 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2948 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2949 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2950 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2951 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2952 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2953 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2954 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2955 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2886 0 obj << /D [2957 0 R /XYZ 28.346 0 null] >> endobj 2956 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2982 0 obj << /Length 912 /Filter /FlateDecode >> stream xWɒ0+t)*[lSpap d >MZl9DSoe  Fi|O Dľg7~tyA \v=y2V by&^6'O_ܾ>1)ˠX(/!ƪ}nVs.MwCԏ]׋bݽWr04O lȡKO"@Sws3&%օc2m"id{S|eD"o}WoSE#G^WG!2cC7"FYXy-2 ^FEJ4^;)X.;5 T RSou=^oJ, <ڒ37 Ay~2D L쩭")1!/&cH*A*JI9RTPEB6S1{_4%/ d)!e4@Bs2z2#E+ؾ])2ᰯO%Q阸TҨ,b ЈćMSDj "i IYr'\0 45VRa6zhs|>5 ) ߦn C0_6:;aK>( y(ud_KeI5YDUdA$̐h!*rSgrh[U"H_`Z)Z }Q0Rd7m3;l?K/w]hCgz[b=[ҍ0>[8m=U vD{?I.)f3:U0(OR_4tbbƬ/o&e|37A endstream endobj 2981 0 obj << /Type /Page /Contents 2982 0 R /Resources 2980 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2935 0 R /Annots [ 2960 0 R 2961 0 R 2962 0 R 2963 0 R 2964 0 R 2965 0 R 2966 0 R 2967 0 R 2968 0 R 2969 0 R 2970 0 R 2971 0 R 2972 0 R 2973 0 R 2974 0 R 2975 0 R 2976 0 R 2977 0 R 2978 0 R 2979 0 R ] >> endobj 2959 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (C:/projs/slides/2013-02-08-Kaiserslautern/gpu1.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 2983 0 R /BBox [180.452 407.506 281.865 487.791] /Resources << /ProcSet [ /PDF /Text ] /Font << /F8 2985 0 R /F11 2987 0 R /F13 2989 0 R >> /ExtGState << /alpha1000 << /CA 1 /ca 1 >> >>/ColorSpace << /PCS [/Pattern/DeviceRGB] >>/Pattern << /Pat95 2990 0 R /Pat96 2991 0 R >>>> /Length 398 /Filter /FlateDecode >> stream xڽMo0 <.’DQl܆6씦~)u4ͯz(Wa?Фc`#,bF Rx 9)ː~*|)!J6!a"snt&efV]5XU}?[7;mQ9a/(A{'3{['F8#lSwL ϗSj>e&s R҈*v) DP%Z1\9 jǛ{ɓ뿛3}tfɼٳrAaOQ=c8C˵xߛ1F8t 8G -'==}-:aM!ZP, endstream endobj 2983 0 obj << /Creator (Ipe 7.0.10) /Producer (Ipe 7.0.10) /CreationDate (D:20130208173232) /ModDate (D:20130212181322) >> endobj 2985 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 117 /Widths [ 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6] /FontDescriptor 170 0 R /BaseFont 182 0 R /Encoding 2984 0 R >> endobj 2987 0 obj << /Type /Font /Subtype /Type1 /FirstChar 66 /LastChar 68 /Widths [ 758.5 714.7 827.9] /FontDescriptor 173 0 R /BaseFont 183 0 R /Encoding 2986 0 R >> endobj 2989 0 obj << /Type /Font /Subtype /Type1 /FirstChar 48 /LastChar 48 /Widths [ 329.4] /FontDescriptor 1014 0 R /BaseFont 1019 0 R /Encoding 2988 0 R >> endobj 2990 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.5 -0.866025 0.866025 0.5 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2991 0 obj << /Type /Pattern /PatternType 1 /PaintType 2 /TilingType 2 /BBox [ 0 0 100 4] /XStep 99 /YStep 4 /Resources << >> /Matrix [ 0.866025 0.5 -0.5 0.866025 0 0] /Length 21 /Filter /FlateDecode >> stream x3P0P04bT4.U endstream endobj 2988 0 obj << /Type /Encoding /Differences [48/prime] >> endobj 2986 0 obj << /Type /Encoding /Differences [66/B/C/D] >> endobj 2984 0 obj << /Type /Encoding /Differences [48/zero 67/C 99/c/d/e 114/r 117/u] >> endobj 2960 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation104) >> >> endobj 2961 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2962 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation106) >> >> endobj 2963 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation104) >> >> endobj 2964 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2965 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2966 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation106) >> >> endobj 2967 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2968 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2969 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2970 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2971 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2972 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2973 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2974 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2975 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 2976 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 2977 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 2978 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 2979 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2887 0 obj << /D [2981 0 R /XYZ 28.346 0 null] >> endobj 2980 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R /F39 78 0 R /F45 164 0 R /F28 2515 0 R >> /XObject << /Im39 2959 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3015 0 obj << /Length 1355 /Filter /FlateDecode >> stream xXKs6WVjFD"؇=CM'|($ק.)YnbI `[,6AD9) !KOKL@w=wyu%Uhu(K01`Zџj[,b.h4۪3m[+p(c-f(f)&Z[W?mpf}ٛM@9*vclF &Mnf5YFSEEmYG+lO&`O /\]tPdB8I)ba4kD^,$S %+2:+mm% ɫ|y)ɲzs7z8R80\wq?8#qO/':Z[}6c5k+}0VreCZ6r(;{Eg^f/Â/hIӼFA#vDcuZiE"-_ںY|' $م)a ߆֎eZpY-B;:mhھX.>⑫!TD]\sny6۹<[GϓϨHç$K{y򽅥BR$oHYz.i.AĵJ=2& ^qsJ!%JAv Zkjd$,:p` ɎQBg^inhc8oͨ.YMVS vr4+/ᘹ)5SN`S$Ɯ’)ڵx>A&D([&+0 4c|"}NP44LgNgx}'0{15?|)}O":_9Lζz?@]) Qi"Q"iBDLΤ8!<=:.< o ) =@k Aѝ$ >o ZtDY2_&X>5sI endstream endobj 3014 0 obj << /Type /Page /Contents 3015 0 R /Resources 3013 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2935 0 R /Annots [ 2993 0 R 2994 0 R 2995 0 R 2996 0 R 2997 0 R 2998 0 R 2999 0 R 3000 0 R 3001 0 R 3002 0 R 3003 0 R 3004 0 R 3005 0 R 3006 0 R 3007 0 R 3008 0 R 3009 0 R 3010 0 R 3011 0 R 3012 0 R ] >> endobj 2993 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2994 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 2995 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation107) >> >> endobj 2996 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 2997 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation106) >> >> endobj 2998 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation107) >> >> endobj 2999 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation108) >> >> endobj 3000 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3001 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3002 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3003 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3004 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3005 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3006 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3007 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3008 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3009 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3010 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 3011 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 3012 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 2992 0 obj << /D [3014 0 R /XYZ 28.346 0 null] >> endobj 3013 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3040 0 obj << /Length 1351 /Filter /FlateDecode >> stream xXKs6WVjFD"H؇=CM'|8$ק.Hr8nl~Ȗ0rqƎV+=PZL&DrI_۳׏>usΨa[EBD2 =ޕX4[IM]6HnbUE(K2cPE*a,nڲRF7P v`[گx(M[]"rfQnt-9*e>"ܡǎOJ-Y\r ihr",3h&?w'~>pK(Piۮ*v@YWA0oYŠ:Xyެ)d-BHuNFy{SwS9U?1 %v 8xX`:xϹrq#ܝ2"n<'_[ftd&}aFNfπUy>xՓnP2+ol6)x ėZqfǫ rַ_8 :m?5|{?a@^aPe$IyBYL V|1%@ %E$^&.*A).]_l2>YF ad&J2=^ 5l9.Ḷ0E6l"D?Wr=t/O'<0_Hޞ gH<3%4󀌱UK :ev w endstream endobj 3039 0 obj << /Type /Page /Contents 3040 0 R /Resources 3038 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2935 0 R /Annots [ 3018 0 R 3019 0 R 3020 0 R 3021 0 R 3022 0 R 3023 0 R 3024 0 R 3025 0 R 3026 0 R 3027 0 R 3028 0 R 3029 0 R 3030 0 R 3031 0 R 3032 0 R 3033 0 R 3034 0 R 3035 0 R 3036 0 R 3037 0 R ] >> endobj 3018 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation106) >> >> endobj 3019 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 3020 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation108) >> >> endobj 3021 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation105) >> >> endobj 3022 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation106) >> >> endobj 3023 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation107) >> >> endobj 3024 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation108) >> >> endobj 3025 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3026 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3027 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3028 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3029 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3030 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3031 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3032 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3033 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3034 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3035 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 3036 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 3037 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 3016 0 obj << /D [3039 0 R /XYZ 28.346 0 null] >> endobj 3038 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /XObject << /Fm6 1440 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3063 0 obj << /Length 1107 /Filter /FlateDecode >> stream xXKo6A,86@j4hQ[҃,kB 7w^u z1<#r ab#%ũ5S Y-^?0zbG0Y@j\7OwDzJs]m~wvWRbfK(o|4߲]PZ(8+RIMI5eքпnC)vE baE"ʵ ZKPV0„(ڽG$wfw&3bӹٶۍags;R t! Im-IvcZݒQEjf8;0@%Cu !4F˿ͦ6Xe%DCw%JT"XW%מI,nS뮉1qa4&Fkb& dA1< T0=A]=s"i`T&, p /OH/M}!tclɍlɢm{DS GT1ؼKu}nbsB.kƊ.}GP {*CcpCI~Jp wd@"a~G\]m5"0ZQ W%YvVFʐ܉CbhǨ=9 $JV/aRܞn53BGº945A$9uK! USID}v8c 2SfZ+\YŬXD>D_7S)&oi`4Lg&՛$Oh>▓65_ჼ+)oOtk%*e:$Y.f(α8$=ҺuB&E%Uq.$('/`Y)|* ӝ$C}uUyUY 慘$4S@n endstream endobj 3062 0 obj << /Type /Page /Contents 3063 0 R /Resources 3061 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 2935 0 R /Annots [ 3041 0 R 3042 0 R 3043 0 R 3044 0 R 3045 0 R 3046 0 R 3047 0 R 3048 0 R 3049 0 R 3050 0 R 3051 0 R 3052 0 R 3053 0 R 3054 0 R 3055 0 R 3056 0 R 3057 0 R 3058 0 R 3059 0 R 3060 0 R ] >> endobj 3041 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation107) >> >> endobj 3042 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 3043 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation109) >> >> endobj 3044 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation107) >> >> endobj 3045 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation108) >> >> endobj 3046 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation110) >> >> endobj 3047 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3048 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3049 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3050 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3051 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3052 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3053 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3054 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3055 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3056 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3057 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3058 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 3059 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 3060 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 3017 0 obj << /D [3062 0 R /XYZ 28.346 0 null] >> endobj 3061 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3089 0 obj << /Length 1112 /Filter /FlateDecode >> stream xXKo6A,86@j4hQ[҃,kB 7w^Ih^Lpߌ5#70"FԄkN+2tdx@Cg?!erEtM…P#皼*~;Pםln\pڗC_6c_Bq|@6W B-/_JjMM*)&usJдcFdohKg3R'Q@Z`%&D}>Bu5e n 'vۑϗ+i֒1Fo-Ռ_=*T3ד*04PPۅ|F˿ͦ5X]wMJJ}JtW"˕c?],UɵG"4hg]}.Ch,&zkb$dN} < T0y+ )3#dBc%qB%1(q,UA Kt"na:#h67{ N6mp[d8x{ ) ܅ ʎۤ[?.kƊ.Us>C s?'+&TCrEVR_pp!Md q*r}jDPa /Kx鴌$!$\QQi-6-9$\rVρb+؞.KfфrĿ.V rg犦 $$<ϱЩ#SH(Ho#}pBϰ 2&' `_ ?aFkB,FbsU.ᔊ$[ w3)dt'YBGNX8L^~~Pމ{j/ )|~l>_o[#}5QV)W,S '_-pjJ#ѭ{2)Id!I9?Ǚl&[cGE0dL]b_i@5e=ˈ@}BsjNE]t,ܟ6_<Φ ۽t&KP'Jdp2>N6yPǺ<,DL($ S endstream endobj 3088 0 obj << /Type /Page /Contents 3089 0 R /Resources 3087 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 3090 0 R /Annots [ 3067 0 R 3068 0 R 3069 0 R 3070 0 R 3071 0 R 3072 0 R 3073 0 R 3074 0 R 3075 0 R 3076 0 R 3077 0 R 3078 0 R 3079 0 R 3080 0 R 3081 0 R 3082 0 R 3083 0 R 3084 0 R 3085 0 R 3086 0 R ] >> endobj 3067 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation108) >> >> endobj 3068 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 3069 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation110) >> >> endobj 3070 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation107) >> >> endobj 3071 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation108) >> >> endobj 3072 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation110) >> >> endobj 3073 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3074 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3075 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3076 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3077 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3078 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3079 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3080 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3081 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3082 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3083 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3084 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 3085 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 3086 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 3064 0 obj << /D [3088 0 R /XYZ 28.346 0 null] >> endobj 3087 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3113 0 obj << /Length 1109 /Filter /FlateDecode >> stream xXKs6WV@ xәL;Ժ5=4eqW(zҿœ-ͣӋ,!\,ؽp"85&\s \#B:~\|=Zf,WDT \X 5Rɯ7DzJs]m~wvWRbfK(o|8߰](-KBԤ2k7AݡP M;m4Axt0"uZ  Z_q(+nn]`B#dq{~\Y~[V@lưnsar:0 Im-IvcZݒQգ<@5p=BrCiX]gDlQs9u״X!Ew%8cń^\{q~{ %rv {vO5rq94ΌFzDK`M,Ш/ԙG ??03mdxCs`BLuU;fES ˢ] Qڶݑ"XqRh"REc.E;tpWY3Vvfchj~eD!2ܐ{_.~j%\d񀝜щ$a#NPqW[̀*pd<%$NH ΝP9')ƊrJkdQx7$`("ߝx \0tv3*[|tZX;;4M h$q'Qy7~Fݒ9q+Cm"|"8dd"} hmV?^Dz)B11|몁jj&ś$M(>▓64{qG C _%ӭ3dIU /*˔ủ$Y.]ΔQcpRI|{uL:Sҫ"iHdz&!khm"QIŃPZz.1ۯc2ewS!> /Parent 3090 0 R /Annots [ 3091 0 R 3092 0 R 3093 0 R 3094 0 R 3095 0 R 3096 0 R 3097 0 R 3098 0 R 3099 0 R 3100 0 R 3101 0 R 3102 0 R 3103 0 R 3104 0 R 3105 0 R 3106 0 R 3107 0 R 3108 0 R 3109 0 R 3110 0 R ] >> endobj 3091 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation109) >> >> endobj 3092 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 3093 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3094 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation107) >> >> endobj 3095 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation108) >> >> endobj 3096 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation110) >> >> endobj 3097 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3098 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3099 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3100 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3101 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3102 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3103 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3104 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3105 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3106 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3107 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3108 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 3109 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 3110 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 3065 0 obj << /D [3112 0 R /XYZ 28.346 0 null] >> endobj 3111 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F16 42 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3137 0 obj << /Length 702 /Filter /FlateDecode >> stream xVKO1ﯘc8ę~X !@ɭlC$;f%Bogyk#=I, #iL kEffrLUH0fWG 5;GWI%f^]mї!j cd~]]n\lwdc/կ P./at|rS6R6Z 4+C&~@r J;(1وMS9,y ?ӻpzgeȝY2SBtAljYFxFNՏBFh(FC>[ʖ{L׍s*zSxi^N10dY#Qz5m-)ɑ>Ynm˩! Ouɥ*X `]H3\u֙w܋ִ[0.ARa)+YRt(S@O񖄅D>V|h }bJ*V4,$͸37cwt endstream endobj 3136 0 obj << /Type /Page /Contents 3137 0 R /Resources 3135 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 3090 0 R /Annots [ 3114 0 R 3115 0 R 3116 0 R 3117 0 R 3118 0 R 3119 0 R 3120 0 R 3121 0 R 3122 0 R 3123 0 R 3124 0 R 3125 0 R 3126 0 R 3127 0 R 3128 0 R 3129 0 R 3130 0 R 3131 0 R 3132 0 R 3133 0 R 3134 0 R ] >> endobj 3114 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[0 1 1] /Rect [83.059 140.02 279.776 152.013] /Subtype/Link/A<> >> endobj 3115 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation110) >> >> endobj 3116 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 3117 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation112) >> >> endobj 3118 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation110) >> >> endobj 3119 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3120 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3121 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation112) >> >> endobj 3122 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3123 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3124 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3125 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3126 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3127 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3128 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3129 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3130 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3131 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3132 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 3133 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 3134 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 3066 0 obj << /D [3136 0 R /XYZ 28.346 0 null] >> endobj 3135 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R /F62 3138 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3162 0 obj << /Length 625 /Filter /FlateDecode >> stream xV;o0 +8&CURoVtr. ,%eSrMӠyp2?Q2p g+zd&kFpq`8|BMB0^E41l7.nM̰ װ|=>\D`3a w0 1FΞߦs`Y0W.*{X8`M?o!_JɰcOضq&L}(WV6s{۪cQ&.\idN13y%Gg<<=qPQiX[4kP>YrED<ӨA:=~tM()EJͯpV0XUmSKK)|'n{FUz{k/"v8Tk/7oO}+xһls{[~ޏ$,I.,HQUXDY!`,Q^89Zk\d.4DoAe 25fM%pCeHKS]2M0Ϙ4(T,B=!@g| :mV_alOm?}l%$*RKӄAOքy/v}h/ʮjZ.$d<̇/V endstream endobj 3161 0 obj << /Type /Page /Contents 3162 0 R /Resources 3160 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 3090 0 R /Annots [ 3140 0 R 3141 0 R 3142 0 R 3143 0 R 3144 0 R 3145 0 R 3146 0 R 3147 0 R 3148 0 R 3149 0 R 3150 0 R 3151 0 R 3152 0 R 3153 0 R 3154 0 R 3155 0 R 3156 0 R 3157 0 R 3158 0 R 3159 0 R ] >> endobj 3140 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [222.112 -0.996 230.083 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3141 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [228.09 -0.996 238.053 8.468] /Subtype/Link/A<> >> endobj 3142 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [236.06 -0.996 244.03 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3143 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [245.674 -0.996 252.648 8.468] /A << /S /GoTo /D (Navigation111) >> >> endobj 3144 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [250.655 -0.996 257.629 8.468] /A << /S /GoTo /D (Navigation112) >> >> endobj 3145 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [255.637 -0.996 262.611 8.468] /A << /S /GoTo /D (Navigation112) >> >> endobj 3146 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [260.618 -0.996 267.592 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3147 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [269.236 -0.996 276.21 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3148 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.217 -0.996 281.191 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3149 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [279.198 -0.996 286.172 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3150 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [284.18 -0.996 291.154 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3151 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [292.797 -0.996 299.771 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3152 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [297.779 -0.996 304.753 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3153 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [302.76 -0.996 309.734 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3154 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [307.741 -0.996 314.715 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3155 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [316.359 -0.996 327.318 8.468] /A << /S /GoTo /D (Navigation1) >> >> endobj 3156 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [325.325 -0.996 338.277 8.468] /A << /S /GoTo /D (Navigation113) >> >> endobj 3157 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.921 -0.996 348.887 8.468] /Subtype/Link/A<> >> endobj 3158 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.895 -0.996 354.865 8.468] /Subtype/Link/A<> >> endobj 3159 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.872 -0.996 361.838 8.468] /Subtype/Link/A<> >> endobj 3139 0 obj << /D [3161 0 R /XYZ 28.346 0 null] >> endobj 3160 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F18 43 0 R >> /ProcSet [ /PDF /Text ] >> endobj 3186 0 obj << /Length 1240 /Filter /FlateDecode >> stream xXKs6WV cn3iɡ큡iHƔ.lq6nNϞK+Z!Ï1A:pT󜀠 ) Ya'3:$'b(זYAɅ )s8uRFe,$e+4Qx7$pH"_x L#T0qZϙC0MS BgsԠIGp"EP>ϑШ2'P|w NP#c(F## laFs3OF137n70=J'v&jqQ Qτ? ko|ٌ3O?̈}~D^hwLY4#IPPjG.dh16i^"I%^)8FD1 ILVFɋHInFwB):;G_\~e)ˈ/]=2Q02OQ~cM+j]e:y_\kwyJ6LSv!h,?I::!AxGJ3Iƃ2EŧQ%.bP+zGIյ}=,^7@^vxÈڄYK w aqGD6s1Z3WXyt/ʽ2m0)nSW/Lr hqe Όs8ZK~\ g?.WΪMhۢ|ww2̻yXة n8ʩAM9v1.@O5_ź3Z!ӭ>vs-znL#J BG߽.53yY]~BݶQTB쯞um Dt^,(;+) 3sCIYHެ ]l]|} ˮnbfQy߷;5´ t6_u]zTk~_|,+ Wݾ^K*[j %vXos* p{9(n ;J0yp}#?G}0i c@]B6OhTWfW'KXֽm>m TDW% endstream endobj 3185 0 obj << /Type /Page /Contents 3186 0 R /Resources 3184 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 3090 0 R /Annots [ 3163 0 R 3164 0 R 3165 0 R 3166 0 R 3167 0 R 3168 0 R 3169 0 R 3170 0 R 3171 0 R 3172 0 R 3173 0 R 3174 0 R 3175 0 R 3176 0 R 3177 0 R 3178 0 R 3179 0 R 3180 0 R 3181 0 R 3182 0 R 3183 0 R ] >> endobj 3163 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [230.631 10.928 238.601 20.392] /A << /S /GoTo /D (Navigation112) >> >> endobj 3164 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [236.608 10.928 246.571 20.392] /Subtype/Link/A<> >> endobj 3165 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [244.578 10.928 252.549 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3166 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [252.32 10.928 259.294 20.392] /A << /S /GoTo /D (Navigation112) >> >> endobj 3167 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [257.302 10.928 264.275 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3168 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [262.283 10.928 269.257 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3169 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [267.264 10.928 274.238 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3170 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [274.01 10.928 280.984 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 3171 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [278.991 10.928 285.965 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 3172 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [283.972 10.928 290.946 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3173 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [288.954 10.928 295.928 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3174 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [295.699 10.928 302.673 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 3175 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [300.681 10.928 307.654 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 3176 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [305.662 10.928 312.636 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3177 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [310.643 10.928 317.617 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3178 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [317.389 10.928 328.348 20.392] /A << /S /GoTo /D (Navigation1) >> >> endobj 3179 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [326.355 10.928 339.307 20.392] /A << /S /GoTo /D (Navigation113) >> >> endobj 3180 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [339.078 10.928 348.045 20.392] /Subtype/Link/A<> >> endobj 3181 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [346.052 10.928 354.022 20.392] /Subtype/Link/A<> >> endobj 3182 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[1 0 0] /Rect [352.03 10.928 360.996 20.392] /Subtype/Link/A<> >> endobj 3183 0 obj << /Type /Annot /Subtype /Link /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [188.925 0.924 309.206 8.23] /A << /S /GoTo /D (Navigation1) >> >> endobj 52 0 obj << /D [3185 0 R /XYZ 334.488 0 null] >> endobj 3187 0 obj << /D [3185 0 R /XYZ 334.488 0 null] >> endobj 3184 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F19 41 0 R /F18 43 0 R /F39 78 0 R /F21 79 0 R /F16 42 0 R >> /XObject << /Fm1 12 0 R /Fm5 53 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1 0 obj <<>> endobj 2 0 obj <<>> endobj 3 0 obj << /pgfprgb [/Pattern /DeviceRGB] >> endobj 3188 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 3189 0 obj [500] endobj 3190 0 obj [288.2] endobj 3191 0 obj [813.9 813.9 238.9 266.7 500 500 500 500 500 737.5 444.4 480.6 722.2 777.8 500 861.1 972.2 777.8 238.9 319.4 500 833.3 500 833.3 758.3 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.4 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7 461.1 683.3 461.1 461.1] endobj 3192 0 obj [639.7 565.6 517.7 444.4 405.9 437.5 496.5 469.4 353.9 576.2 583.3 602.5 494 437.5 570 517 571.4 437.2 540.3 595.8 625.7 651.4 622.5 466.3 591.4 828.1 517 362.8 654.2 1000 1000 1000 1000 277.8 277.8 500 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 777.8 500 777.8] endobj 3193 0 obj [722.2] endobj 3194 0 obj [489.6 544 435.2 544 435.2 299.2 489.6 544 272 299.2 516.8 272 816 544] endobj 3195 0 obj [1055.6] endobj 3196 0 obj [253.5 283 519.1 253.5 843.8 548.6 531.3 548.6] endobj 3197 0 obj [272] endobj 3198 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8] endobj 3199 0 obj [447.9 447.9] endobj 3200 0 obj [826.4 295.1 354.2 295.1 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 295.1 295.1 336.8 826.4 501.7 501.7 708.3 708.3 708.3 678.8 767.4 637.2 607.6 708.3 750 295.1 501.7 737.9 578.1 927.1 750 784.7 678.8 784.7 687.5 590.3 725.7 729.2 708.3 1003.5 708.3 708.3 649.3 309 531.3 309 531.3 295.1 295.1 510.4 548.6 472.2 548.6 472.2 324.7] endobj 3201 0 obj [666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.4 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7 461.1 683.3 461.1 461.1] endobj 3202 0 obj [586.1 586.1 891.7 891.7 255.6 286.1 550 550 550 550 550 733.3 488.9 565.3 794.4 855.6 550 947.2 1069.4 855.6 255.6 366.7 558.3 916.7 550 1029.1 830.6 305.6 427.8 427.8 550 855.6 305.6 366.7 305.6 550 550 550 550 550 550 550 550 550 550 550 305.6 305.6 366.7 855.6 519.4 519.4 733.3 733.3 733.3 702.8 794.4 641.7 611.1 733.3 794.4 330.6 519.4 763.9 580.6 977.8 794.4 794.4 702.8 794.4 702.8 611.1 733.3 763.9 733.3 1038.9 733.3 733.3 672.2 343.1 558.3 343.1 550 305.6 305.6 525 561.1 488.9 561.1 511.1 336.1 550 561.1 255.6 286.1 530.6 255.6 866.7 561.1 550 561.1 561.1 372.2 421.7 404.2 561.1 500 744.4 500 500 476.4 550 1100 550 550 550] endobj 3203 0 obj [536.1 536.1 813.9 813.9 238.9 266.7 500 500 500 500 500 666.7 444.4 480.6 722.2 777.8 500 861.1 972.2 777.8 238.9 319.4 500 833.3 500 833.3 758.3 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.4 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7 461.1 683.3 461.1 461.1 434.7 500 1000 500 500 500] endobj 3204 0 obj [523.1 523.1 795.1 795.1 230.3 257.5 489.6 489.6 489.6 489.6 489.6 647 435.2 468.7 707.2 761.6 489.6 840.3 949.1 761.6 230.3 311.3 489.6 816 489.6 816 740.7 272 380.8 380.8 489.6 761.6 272 326.4 272 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 311.3 761.6 462.4 462.4 652.8 647 649.9 625.6 704.3 583.3 556.1 652.8 686.3 266.2 459.5 674.2 528.9 849.5 686.3 722.2 622.7 722.2 630.2 544 667.8 666.7 647 919 647 647 598.4 283 489.6 283 489.6 272 272 468.7 502.3 435.2 502.3 435.2 299.2 489.6 502.3 230.3 257.5 475.1 230.3 774.3 502.3 489.6 502.3 502.3 332.8 375.3 353.6 502.3 447.9 665.5 447.9 447.9 424.8 489.6 979.2 489.6 489.6 489.6] endobj 3205 0 obj << /Length1 1652 /Length2 10757 /Length3 0 /Length 11822 /Filter /FlateDecode >> stream xڍP]. w`pwww 6 C<w@p vޚwti;ZV  !VpppqppjAA\ NB`H BT8N>!N~!࿈W! @ qJC\ll/qu0X28Y4HAv@'*j D: v `B=<<؀`76# j \߁ PAƆJ жsKz]A% xRTu9EV8N6GvN--!`g x+NVn{;#Ձ9I %ÿsts9#n^,d% ANP7?'c |upx8y Y9YY3;HQo΋?2'@rC3`|@]AT7BXYB ;'x/wq'߿O&/fqr+(0RRO7+/9W_)U}xTtJzJߓ0;eA1/ˇy 4?_o$/G9zxgwnB^6zZ h:E(eC$l]F;79;O!W^;9!nv<8VNѽ윥ˣҫ?UN?v@WWK_/eI@6 }1$ QA~;_Hno}ح9@n? /P2N/!<|vр#6'% ^pspz O_twu}yw ȁ@ KY7ՒۣSz)_02V]K&vc/m2\I,PqxqEμ_.r$!1$&{u;̧ 6^E RPߋ?=~,舵4jƿ"6&9zo?E$y\)])ecFNo\JD8cRE#cf'4HTg7['YB}&2FTSYdKq3P?: r :rF@ha ƐSMXI'YS#gWtkY4aҵ 65Òݩjd%f d T;< cwT3 h8Eِv$z9&Ayjݶ[wf67>: ҅j*S ܑP!O`(H.*I=JfwE@Ðۺ "|bj8"E1'( Q5RżKq#2Ö(tE$%Vݬ@rLn;{VR(점ag$Zζk,$D$}cr)Cڃ =J Wuu mcxq2";>6DE.z N,4@"k{h+qXG*f2n+ەd 4<--L¶r:b cZB{-|$N`sCcF́:Us1`ղEͼTuALߪ:ȎD?&DciSgN|4k߇كT׶ԯVݍ$|fQ?2;vLvޱuA=[ JPNd  }XAJhuWұH%ʛ 2NUT^aK2>7t=Wb{vG0x-ZܻI C'jXROu[2w&>lKZbaȓOX:5גVhzU>3iIa d2fW8Yx+V5~6shvFFW֍l*W~һɨQ:lQm ޢ Y唷F#N. vlؗv7zsvL YϾ6£k%~U (:=-Y; sޱ]oaaBѐT6~aY7{ nMWںU(7f QaF@xRd<C[w-bb"nq4zh+%d=r8)}.rS(Eth;VxbY#ʹ1@OxJ3]=m+m(7th}SDѶԎ_^fD׳rQ=5JVBHltclPY&cŀٛ8`R@5LTTt eiy.KԸ)G1B `eBc6Uk ܟEvk)Q%9~[˜ihs1iH"V,US|֙,Σ>g bvh5 iLJLɼ7mն{UFRraVXTh:o2@L4NuneU.7}Di I^,aPҒl((i[bp]euR%653փ. jGMx2;w ~lw=N8HB8l#q>!| 9q[ke6{?:#&7՛.N#l+ 5\]e&me+Xow0^&#>8~;rhnvT!^, ~(gq~q,T˕>ahEd )x =f<ʡZ'౿n݇ IbM|&|ޢo dYϚ;!*魶QbE7^QlғtA:ʼnƊۯ])2lH3;ׅveĉ_ bK:"nξxIмR`+&jwAWN%hlm<'`Mk;Y_vAզ !E{!8\AJ.X:gko[Ƕ̡.T~,>^hyq77^4=ΌϬj )dh3lHEa=ߔ0|S89i8U^D- ϰdQ+c&7fiq>2& @\ȅ;gwp[UgO!]M迖Kr"jD۱ 5Ffe[mGQsPL@nFS#:o~Sĺy>_ܔW}B @8At $-B>][2n1a򟪑p1c:2E?ZiV%Nl#c|Mh!rKʯ*z1O68:hqԃg{.ӊDψɆ({qYY-+l^,yC5`< EI=fHTF^ӌϏTų+\e0d2y+.ٗ1 ss}N[ HY_0vI֞ א/ӍN=?[Ʌ.h͊}CPx#ft.G L~)!6-6A  ݨVy)A*Dzoƛ̶laE⟟y|/sSNgs~gH-YG[Rw: rmÂT)E z P)A3/W5uɮVh:ġ|;Ri_ՆjNMt?rf6L8hcNb8 '5l7,@B2S_D'>2WЖiA# T= a zdS6I'q;PF!"Q, 0j^\oB/rOGnL=? R/,MRD:%6cRطlse& 򫍞Ѽ5m ^{Eu!sc:2l#0U`'%fܣWoV  )Q~H_"V-=o$4݇pN?e=.#)?UGYE͋K_8'Yy-/*aM9,rNܠij-+l}bl&@ +}lvFZ {(]oNr~FK\ibSJLz|:bM,ec bA%/!y&n % V7F`w8ESeLyhDЁr0HPA2@Kn4*|]lM+!snk7Y&ݷ1ЅY33d3V!u{>qȹfq&W.6E`U/ej/T,p6N5+ŁJ=XO^{M6_~ki浆\}ƽ$,54o]V3R5Ȍk*I/](.]L?>~K;ϐh{<*bcL4 g}pRipc7V x(AUiZc1{Vmu; ?ӑOP.Z.K g@*̪c>J{vlj≚"lKM9],@: 1> lFW[/ ٱ{ )v'w-`S$8RRG' Dxܝb[楗`{W?k:L}U8] Js5e]i){N7rcMíolSKי1לpd\X,cq_!BgJхwO Lddj9ᐾk<x*PeRqsȁIޤuhF`TE9?I^=AAiVԶ4 3u0_}q,1Z7= ~I1$ئT"@ݹ!UƈQJ$:j|m_LuA`dZH)iH^}f.cdTCαi)YxD JKReP]ok ֹuӬbM=EnjhT8hju󹯕ůOprb8|􉀞ʓ ыI /8LIZ_1?hnjm(} rjx70\ZҲ>/ҵŤMSb 1 Kd}oS7ȜɧQ8;5[VJ|5✬{Cui>ln+^_{&:_ # ?ξۺ+Z?3Vc视$Яτ\usC@NJj-?n%̮^53=_W(FlQ}K+ ;=Έ WҔΉyCm;)f>1[3b{{1ޒP٬9kFFҀ[HƳ-ذT ֒JS=|>Zl1"vhΪ@I;]=s51~Qr4hި\ǬX(I{c$GO5qdzщ†iy! 5>dp[hē̽>xǖgF"}.IqӔ]Ŕ־'W-~s*A H@x\[3ci6.I%V/bzsM',a\(N3TyfcӞ۞kq xVDbI0)_(Qa)y: G7o&cTj|;,!s9B(.=TаU3铨;ї 唝3bϭ7O QdHqsǯe@ŬO#l@TҜDbH2zg(N)c(kW: (˰ 1CcH案3ӕ_@r{\1lj̑դKӭ.GAs >=gbƉUUw3f~=[ AXR衊m!kDθOW\1=Ɓ5!h^yd1R㛹gmz5$EoY_Ns90_!w' 3U2V%=ši բFMZ(J`d/ dխ6mKW&\-_5OiV=}F7ڑJ9Bdu/w vjѠP"~:c"Ҫ7.>O(دޜȼ|}{N/J+T޸d}+);1 Ksȋʂhp`e8lʼn)yif6Fx;Z5tؗZc,Qc~GsJ!v/e{HA{mw[uXr#s8(Ė77SaLXe3?CvwmE z<4,<PK_Ey˴NRgZVuϘewͿ|Oonu3=ls-iYOΐ23'Q~j~$5$~h쪣P@nB2cpr0ߋ˭3lsH9qܠ_d=vL|Rp68>;BERpz`)߮^R|Z ~DUҳDdZa;6|tDie"tAo\c@;hq* ϖIZsl-crs@ 920NUvZEi-m3fM{`xE&R xA伾['=nZ$Qx^c;#N*0yO?VqDQp/C1M}aHz:s_sɢk_F ?vuYz06Ll}M);~ f}sUeXG~0IA5a0<ؘ9eD>`n&&"Ϯ=gn;Q`| 9dE{SXZplЦDlj" cVQ# fTTc /9=beX9~rv]r{Ħ1X{Ī; endstream endobj 743 0 obj /GHWWYH+CMBX10 endobj 738 0 obj << /Type /FontDescriptor /FontName /GHWWYH+CMBX10 /Flags 4 /FontBBox [-56 -250 1164 750] /Ascent 750 /CapHeight 750 /Descent -250 /ItalicAngle 0 /StemV 114 /CharSet (/a/c/d/e/g/i/l/m/n/o/period/r/s/slash/t/u/x/y) /FontFile 3205 0 R >> endobj 3206 0 obj << /Length1 1675 /Length2 6709 /Length3 0 /Length 7741 /Filter /FlateDecode >> stream xڍvT}> - J %Ȁ#6KnnK@P: ABZ=^KKfVA\@n^1ˇĤA82nTrp0ɃHEu Āb>^^?ap1<bP/( (_%/;T@O&GްAh07F~[7?ߌݝ~( qhwr9aWFm EU @*$Mт ?t`nw  v֎{ ٭_U\?>A!y"< |={o7@08Ϟx kG0jEXA~ c o_$G5G\#dnοH?p8:fyu^`kYxC]hEOGSLl\X)lYg2)Ck ~4`E>n~3ц;7N>0V+SOCͥ' N jc\ y~FNߑPż-6|vL!bHyL%dtE؏3A4{ :#otē X_ի>gS|j[< f%#Fk])ZTWgOk*uM[}g`+HztyP:~tqUWRGK1&cQ*U,fCW}aZUw\`Zt@*Yi`P|iN4J O X`BY+Z,&xgҴs;m߼ŻpBY.crEh?(.=A+d-l[C5I +v.}n=K>8h KrA\QBw8nY;ۨ@R9UX&yCxtW: 1V.,ojhjY9= jb {<]nH**/R'gWO(dXG𚼔]/Ƿ{|Z.y֙ŽU]EO,{bGPm^%@1; uJ@p^=/ʝ0C)46)/'L6/-X|c 7rfyMifH⏤߫prOgh9s 1U?!mfe~E*"ڵO!ӒENɐWHNtm]5n; mʞ&v oF1ɵt1"w?~z!ty|/oC[G9,RӠܪE/%G^=^݅F+,xjSɜ~B9))w{)MA jhx5)>t- j%-=$UaZ\@yKѯgJoN>uA}P6څ%$q&A~n&HBF9 Z\4FoQ56SSy6#fKQnD޳GJ\ }ubR:q݃!cZ'BJq&ǭ| =L zef5|2Q_YoJol5gBavNb0WDߘv![gRLzrjw#! yu]Ih 1JE.GbgAC5&yɉlzr]_R H`u:8g"%0 `[zA)"h}C"«2=,fɔ夰8?R89P{TT;*N]s40a`4dVbŹD goLM31.jk 񫶤"%Ax)nx΍ihgyֹhz '|, 0oeE0+ +=λB! SX<7jPֶvJ@poA dN,D]0`$|-\zV'uq1sDw_ǝ wRaZsS/A2yAJ"wsy쇷pO h*/o/WG}jxp!#H3 W+bc71i>RpQ<>QΟKu2WLU < PMM%Djv#R=>J .tMKPdl^҃[s?WW{-"N2#Z@̓xc: 31 OB^[!,~殁ˋQuwy)q)"c+Efkyi9y k ǝrmuDE blu0͇cM]t;d%B8XmWHMQPmZR[y7 m8ݴ>e;FST9M}݂[`q|:I3ctkYuAaxN\l㫩Ԇ#Mggwʰ',gajVǏZFt ﺥ* kdҮwRN{˸7n:Y}~Y=If BJaIbb.WRiDuѧJh.?LO6Tf<27&fϊh Begv+6ꢴSmZuNxhO۲^xg@{M0rKYokOtla!qjJTB6qN~ v{`{[%d*ϫV$f(dwZ/Mvͺdh탳M Bl,H=z!΀qS>S+JYҕO\Y-@<e$s8m[-xx{Bǃް-@q1k021l,֒PyMHҽM4 YQұKSX2V,[ rh._Z]&$r[m^)khaG%= ^)d}9c;'+tJ03oDnlvAQB2Q58k)Z󭾑泉z:dM^z>xw[ H4T&=\s-x {ק}_7$vu5 :ybwzpO ͍uYd>I8ݷ4ƒt ~3RjyiBuD^N N>=rQ0IDXE )MiR(~3-\X#'aU+m w9nNL{ FSP-c!kKt_9kn?#2}鐀]k$/yc瑉f W8Y6oѺf  3ӡ{Y|D򬣆}<%\C@2k#O^zlVQ } IZi' R`u-ԚདE5"6Z |N+Ye}Zp"2hy-1<Gl+Y=rz{I9#LBuw<33cKAjrwű^{ut#lwUdq0[ʺusoc,.F*g/{V,r^$t6ݢ<ӛGy;STm&4 o5"7nJㄝO壗_L@O3D@kb#ڼ9f t Gi =3eDm|V?B(X j]g{rrgws(C̝D\Di.ow*n~kwÎiY<&YxDEK@Omfjڟ/|ss36QDۏݤS~QJx\z,'SJB9jyޠ;bU;qK'%qڨy r%&I'I> t\5Щ-W+}l@s'~w2/_k0Zؕ઀ZҽJ㛏~*$̌R&sN8+{GyeOL; ?3l*z_eT,̿p ]m\GG@m1EZN ODyӘRQ^d2l%lT}mCh[JGf "rT{ f` %Sp̝0?͗_./_fzB~acU{åOzWKT{᮸̅"uGU%(݌\i%*ŕsz*;ǃE[V:b}}ҏui*n-3F]G/(O]W2fyn H쵤K3 ϱl}IyP]0 {zD(5l`lU[-OjfȺx4{LIߚqV_ĶgHN o R\zg:OZ|34M0bWkxY@0BA`Ph=EaZCb0b20USjs5^_= 6¦T~9ݗ'(Bc01p8wȢ>pWHc߱2 5~_+<0~ {ҋӄ_l}tajN/PhmuǮ#ԁѻJAfGj1S(inLYy`)2L/; ~4%=&b-'/Tzm֯X $ Nȗ~'Z_@5FKEW=,x1a2kae8\He5u pObaۢw̧pR~Q,uVD;%g\d=V6֑r~sk\&}ׯ+=z.tUd~{5Icŧkj9 Q1`xh"vXg0- endstream endobj 224 0 obj /BZYULN+CMEX10 endobj 211 0 obj << /Type /FontDescriptor /FontName /BZYULN+CMEX10 /Flags 4 /FontBBox [-24 -2960 1454 772] /Ascent 772 /CapHeight 772 /Descent -2960 /ItalicAngle 0 /StemV 47 /CharSet (/bracketleftbig/bracketleftbigg/bracketleftbt/bracketleftex/bracketlefttp/bracketrightbig/bracketrightbigg/bracketrightbt/bracketrightex/bracketrighttp/summationtext) /FontFile 3206 0 R >> endobj 3207 0 obj << /Length1 1626 /Length2 8348 /Length3 0 /Length 9415 /Filter /FlateDecode >> stream xڍTo6N"*!twJ ,˲tݝ]"R4HH J};{333s}eyL[n U;< 2x@ ^"]EtE!BPhÝ*n0,(~*xA ῁p@TPW"Y8 C`brv"aVg:euBg8tV0(B١P ÃGJs<`(;6tZ~ Ѐ8A*ksӠAy@PZ:]ܜH:;@GY : V90pysbewB@`ζ#ƃDq ֿGW89B,р?(Hk C\y\akn, r%}>9j:8=}l`6˰vCa.nPe0hѿ:[( z'$Vv t?jt ~>8`.|\!P OKD`0fXBmaDFG6#ac~`'S4ìΎ^1P_ZANO1=>|n^ ~_g Qdֶ݄}:,O{$yR)bK~jgl ` G,Pɤ# 7#s[$\{2`J28zMrSMS6fRO\kbyn6|]:}&1g-dҀX(ݮCWdA8=;,ZmǛਲ਼SuΥ&9"{a7*.ZiԷsTm ^W$}e<6.`}Cj~7a%V5FF~q H?Ƚ,0rz+Ah-vOTVpKbD{f 4hZyjЧ}B|51)EjM9{%`vb\tq[^:w: x_=泥{p-Nhixky 7C^h~cX9YW E,ּmo>+I I3J!X^d[FlV)ZtŔZ`at`e OQoܖ2ݎV%{bf 6's>r>Zb0J4p`y&xZc2dBub]̢-3x@Bev(q)G/s1I y?"rW؝mf.MuOgjF9שwdBކ 㼬Gg ͏D uIgD.ݩT8E9FPxu/'q(_HB?M%ش5W١t؉ٔ,Cx7(DmŃtݱg`O#br|,uw~_6M0Gxc~Ӳd znAGUYж"!aD;j$~a9ÂO]P+6~쵡B8:ڟ SSe6ڧhut߉iY񑘌Wּu/oFY*^![旈7+!:&ށV$ w`|2}m Ы'wWZmoKK>.^AOaҫ(` Aǜ7J) }'BB7(f8>Wd3G?>@X-kZ G #Ȍ7^5vfTg|MExP6=P-ht)/._XHN5|7ׯ}?? ,:$8Kx$.}U2txK͜8˒[%Jad۾7ǁx]3Er­4GDVy]=![7ѡZz˭)Y a61[QQ$Fv| MOXkeyenų`b5kɝeMS_븗Ռ[܆%'uw6HK=Z9^*:OxeBoH,dGCG}M5tmլ)RM<@a,сqe̝1d/@U,lAO|B/zJJy_Fu^pOi:oӱM؝KoTi}x8H 7^I HQX4Ru5YKyu&n GѴswUzZM Z/ti,{4gZ7O~3щpS=Lhx_CzSGt v0uwN",|O>{&(ϾZ"?G<؞SK5Adܞc4IePŘ&f [+B}seg:\8 iɾe/Gkjmc7z{[ݴNRWTmXsIk4$% Lߓ'>? GtRծ' T}&~5eCūguU;6;n,o ;Y<(Q[۵U9S?1ˆtQ&E7yʻ 93&͡d$:zV{#RQ/}djr#]/4J>iԢg{nʱvίΞ-Ĕv3DPH57vu VPYԍ8d5.sL902H `zi5@.wb&2u$JkVoQ{}_{Nj@" >0hڝ JW5t;c׾y|ҬjAls/d 9G[g ? J1Np+Q,Gfãk ooƥ}|wHQ׬CMVPs¹sO[P]ͳQ5k T r1Ch^$7}1q r87_ o. <⒭v9a 6U.LA5o~+m(=qi}!76Y]m3%;zt)"t htP:mT}vt!,j|J3qq쓗8q|t 7!K!HD[XvHW␷*#I7QmÊv[B+t)9kRQ&RjI4SmwW͓DCl$Z~]Xi7SbOӅx9*k; K8pX|S>A=lP,Ơ$Q ݚ{60)Zse`UA6&UQoW WKV)*$ VZBxW0f4%;E KSCfA3=>ɓ#Y]Q'71y C [6x\E:MDxCK:v5[QQ`<+>;~%(Fc,BS>x|ฑ~쵽b!EhLJ"S.3[ <*OmD~ y.GIH΋WG8 yf;ⶲ? %/vgEcM:JI5@/➣-AOmc/>Љ^Ȉ 3إahL8C< "dVn LY)ހWG 11Hr; í5UdӈoE^& .N7<_U/OE}NNt_v罏+(8$[t]^|l'/>T^lh&vmW~y=wnqNN1amT۵Wv voc{4Py?302$&rvXJKq.2h/~-Vm 1*77Iz_avHMHk;9mWNLc+CAtmb҈@U?$O)X3YըZ*EdE!UKbW.Gu+'Y:$6I?$Gn_Q\uVRbS.+(iKl< Fub~5{Uāe>&Js \_ܕ/>ut(r<NvM m{fKunSЃHǜqjy+ ⤼qR ٵ={= yʘhwfAXVMڨUſtPy.6(} {XѲL8INy Dv]0HZt 6^;V8z2!ߒj4/nJ3v8Kyw(B~{dCGǕ<')'0z`Zu]GbץmOp1Z2uOW02 -]LyqpPw)G>>lY^daфs>8ⅷS$59d}Dj$= >>zUeׇwPjaBucw:5/| SHAja{FRb'~Dv͙V3)*7LʄxˌK<]Wa2skB!6p`${%v;3%ZFAnS}=ɕ-VHz`/-7J.1ߠ릗_?`uqĞ)G'OϵĎimA SiֆJuA.^bW=ŏq~)Q{[eL׌qð~:O/UeFƼAHX ~?;^-гz%Z^pJ{S-$:{ J&,\gp4@ߜ4`$ݽJRˋ~%SnjwܵVjd8Ǎ8yXٷtjBNW)r>ʓ[o%`}Z!",)}b1fv*W-% cn-78}Qt\VI >cAm㈫~Fx"#cmawY| o@`BEu%6=T/Pk5.rOXxYD]*fYL@[&jQ?y4====7lͯRU25< { tp⤩6tt%L rnP-U(##f[^Ԥf-uWod_GCDU![e=%ImK9xtK@DݵtBD#CelPZf ͒JE"qJÁw 8b\wp[;McploW ܮcWG흅ֳ³?_ii 4o?OIi0+ Z ~I\g P䰐VP/p35l趙[rƾZW%|Wݥ0V#ju!lnfzBQp h~s+ewa17^YaIJX歾])#+EdELD01BXر 4kYI׃.%[Sp\MxMz# up 0Y6i8ΛUpHI@yndiiIqR_8~$;7O+Θ ]& ߂0&8>ί;=7d-c ݜSkSqd}Oݜ;,j,u?7Et:߇y>Q'R:kse6^NkKzH[D>9xݔm]`ջVXVDj낈PZ`fǟWe\ꕱFf0_NHQە*8: |ż7wCx1Sh\'cV b5_SL]0̴S7OjI>4Uʳ8B{L$M 25dvX%,#>yUhnj\Ov&4Ect_J(!K5[wQ:PaAlRKY:wVdLOX:TIBHG==J2x/]pdۤsO8GxPTCOkv~ cxf-.zJOm"4.R았L4$Ki,4ZsB<ܩgov;9KYU|:@AfXIQWieN!Lrs[V}~NsIJ&ϟl C1[@%^{$I%-*:|>OMVadcWu I:DDZ #5* r9=꿎-kJ̬`fS6?X㓉[T&=ʁC y!r9Ø~˞̹ )~KZ>X)Vq6M<% 2VvsC<ϴuE |ruir}vn?/B0')Ӆ"xZ| %O>KULf崶HJOQ)J@?D֠4 f}&FZSn' `|J?e~OvOcBw7B";j6 aSE0u]rb)TSvϋ5-^:\Sbۘ S]#F3 d/VX"옵Th;%SFU];`qJd~\8b:"Y8ǭ\mb6䎉_Nf]6RE^AsZGz_y"n{nn:D^ affXnɓ U#aZI[ID,Ҝ-ӧQLUحSIbȦfjD I! mTE] y?B~ze)kaCy4ЙZz]44S< 'k޾"b;YwS4Bb6;+C ȴZgb{K>[3igx &&gxL|Wgp-&l,}Mqz=:kB g܋Vr8[DQ͈a2!PJL |6xu|gC*9Z +'}C{ z6*,ʹGP'RN_t1ަ$J%{Ø0jQ*wJJ2IL9//'?5tR|H>KM;\"9g{yxSvЙ 3輟kT~ $_\5Qz #5QfLVIQq춙1S9|-.Ŵ S38o֪n |\8˒(픞r{8n9<~֏2>{<|=ShxHr[nd_mRPj/Y&_f=r8bm-jޠsSp([u딥92(hS]Z$B</|ӱu|"񘨾w*OԎ?N&AN0ab "syj6w;GZ ʝ ̽H:./p[8ViM׉W9rGz;ww-\|?'y)-YpјXkj/?@M endstream endobj 183 0 obj /VAFDUK+CMMI10 endobj 173 0 obj << /Type /FontDescriptor /FontName /VAFDUK+CMMI10 /Flags 4 /FontBBox [-32 -250 1048 750] /Ascent 750 /CapHeight 750 /Descent -250 /ItalicAngle -14 /StemV 72 /CharSet (/A/B/C/D/alpha/beta/comma/greater/less/p/period/r/x/y) /FontFile 3207 0 R >> endobj 3208 0 obj << /Length1 1419 /Length2 5931 /Length3 0 /Length 6889 /Filter /FlateDecode >> stream xڍuT6(R * %%!6 ]"  ) QP:D3~{}?}_纾f70T($V($"  ss Nпh _PSa($@ %eR""QQhY* PH( 9?xr3]uO(0W y8"+,!r0^ A1P; r&D 0#0( N0!!P4?`w"'NPv6B ` @'(@_]G ' _r!@_Gԕ  .(`@P߁[@ cPIOwX0 O Yi #(J")߿FkB9?5(|(7?^Gx῵VvO+;N^2všKߩfߊօBnĂ"QFD #0O(mg8!PŃ^{G !/DxjH0 S "SoI|xB8B&h 0^Πnٿ8KP'L>>˅8ք4}Rf\엿\TЖ۩6kqVv[c}Z^W`lF.~N9b ,YUI`EFus_S1qFVh^K[UI-fsFE;9sαO#S9[=*f{{߲ rZ R0T>ʧ<)v_OנwX7݈^~b6'cf$<|zs~rr,&,#"?n0;Dw4~ewjkLN_xyɞQ/Bfڼ4|`G y½ԖPYSxW_UL+ M͵ۆc-ֵFg G)0E%'eR12$Its[¶ p̫Kk{RXk*^_(fn^ Alښ{ʎ*SRp& KQ4lm{EὋSFopDQ%A}uF<HRT^L8F 8y`^Xl_:(8^j\AaX 730X h$e_κ3+Bn *Vy*ḨůM zf-9 %bBn0*s󒉈*kR+L9-gIM'Pz2 cz;r_nDMActϵPk;yh3l|&m,IgQ fe#'IV>Nn뢹"^~oyフތk?OzWIY)v 3pS2McEv_[T_&%U@c8LOMP>nIɆm(n K!'Uޮ;^g$;)0f8Ṃ⡘AtmXP5["OlZqGz#Gz- D\R$Fۙ;veY 㮷 (n^kD1=sP OS$}(~1ܕp!y2`{'̍}{n|&v2nǫIHU-t7L}(5 D2uX2-؇v&27dDg8|VBPltbtT.JUNU%aYS^‹McSqor5s4tkJfxelX:zlCT|??dEgaL]|aG ^ȺĸM./[{3/ 0lcޝxd/C^m7pOJ}V#XٟTȬl:~0x}v\֝E#]uZ~{a]HϚ{Z9sBf$V|4l!nXƷ놐w]읽Dt Z% I ZXEaI|hH wk漌ٌFۥ%0xE $Zl' 2u|ni+1Xe6V{NB/G`HjӦ[8N_С$k%ܔ?]wH֩9v?PP~7ba1L/|SP07d v/3xu)^hӎJ34t)'<ҵw^GP.$*QS;u}x 72傓 gC#9%{m*ƥ#ϓΘQ0Bٝ mHլMuwy_;Ms\]=:}+ iG,?#+ڻ4b{XXJEs^D2lv!HHra@wK 3os<%ehTҧ]7mۍ#JMvNK\o/wX} N04 S)3tWKĖtdWʊvY~ !lbM Ymq[rҽ3vXy5\n~Jk](35 .XaP8^jRp4䡞6-'e6G8']4)T+dNbd͞Pڀw$>Cn.PLDs#(^KdY s͘k1RRm.y`M7,YT`3 S3q]|$FIZL/jvONF1^r!.!Jz01dѳ$wBy*kx`HÅ2HӨჶH/ GuphN1ihmO wuOܫtyOU'heV~|TMDD 2Cg#xz~'dFUةgRtǻ"HE,!r)k>Rao\~hv"r{Pd|ڳqleź.8A&vL3Bq v7x~fNYSz}ގB!BޮU0e:8ZDdp8}bgr"`ś8-Pqbхɗ{t>)'EGsE>_~b7*@8qvҎgvY-,Qe\Hf_ᬊ*+P1JasD-Q(g74EeMs("_ھ'Hݯ4υ^>Z:mѽ;}qʃ=_*|U5їR^- Bݟ6;O1ͨ0EPmr=Ր f5=h6t.y-'9S_}vdWW@D?#zNxa過>G۫Ќ.fC9!va!h*G~$vzN g}QELϮ,O~)Ϭp!ApDR3Gcq;Tzt{2VyHh.qVթ\&-YʚMVaqC?@Ji2&WJجncS&6uld#ދUǓmbH 1扁7?d킀qKATw(hQ#!TJ 罞 ;XaorLM"Mx.:](}Fւ`;>o \*>81mٕq}d 4&{{9mAVI5$ Py,NY)k~peסn;m Ɍ.:(C pUNK{MqoY+*֫F HfXiZ_ץfa0.'+/w(["^? 8ݿVW^=,*'nf:pMiFK@ fyΰO{鈰je0#Nv}bYo%M'Kɭ>~$ W r~cH4ZDݱx TWzzIQʡ-Ӳuln57?MVnxq_>ntVs#;=ᕫݵ=ku *Z+S"_#k87?_0J77gZh&΀> :y3U`o jhƠ(,eԟw#ug1ǧŢ1.LK{AQ˖+Ͽ;qI} ;b C lK&̭U"=8k/<^*'uCx4 Zu'[V}*m?y̩/SW}RI'^,f^m$YhrF(\c7%mc],L| v znsGU)e|%,jMnT*_e]M8.P*gSj# kd5xkZӦJU#k&#ƂABiY)֢iė, _[ٙ )9/_kM\R=keKw[ʎt"!OfG|R}\>- rrZ 8[c݂]=G$ YH9[t8,O*t[{2!Vs鿚8VسX_ln$lѿ7%!)uT >@"k}x؉dzRJ/Uu3y{›qЍ씹DaJ{k[!M(nvqѾBan-oFlz.g\5zhwҏ\> to>zn;ü?)niOZHmMس қ%q$5{l9U|ۀ,\ݘ98&M_d{t'??گ~d&Xktl>j@ldV=Zu琎3qH  s둵 ?@bvtܿ&^G8Z1Zh\YRJݐuu=ɖWvvʛo^^{Šd>AWG^'$̟lVí^%wi5QO[DFSuK֠8^,"eXiQNm 4|Fd_#\.yCr8%{Õ^ѥZ3t$ZѠ!)4ABNCazֵů|<)L%Z͍= ѐ6-ݬQQִņm7%udT;Sm'4DΔȵpO+ubv+1 0N?;6 endstream endobj 3209 0 obj << /Type /FontDescriptor /FontName /EZFLEG+CMMI12 /Flags 4 /FontBBox [-31 -250 1026 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 65 /XHeight 431 /CharSet (/comma) /FontFile 3208 0 R >> endobj 3210 0 obj << /Length1 2112 /Length2 16431 /Length3 0 /Length 17716 /Filter /FlateDecode >> stream xڌP .50;K-݃;-}yWzzRCFB'dbkqcg)31YT-ԁ6 q:}D >lmV&;77##?QC =@G&bk`afqT&..?B@ cC9DcC+((y͝\]] mhNe#hC0@2z82_v[S'WC `ea qp1:>H6@ 7&z͟Ɇƶv66fS + @A\͉`hcGGGąh`aHhaD?h>,fc"bkm qr>Q Gٯ66S ?D81X;D0c3:9X@{؜zUw;N? =l"/8OGC o"8&&hfah| 761IcLlm ~%$hR_@`c8> ?/F)S[_>.+Cm?fgu?0^?S,o wMmhmaw(;;}rP _,4p^)'Ï1o--܀&Nnhh@qap_?^(w O{0tp0tdP۟ `uH|:ql?L!? _`P}q}8 Fp0v6?fc[.GCG{L ; ?Y.uvWGٿGEhA. eG*Gm!V|$Tdvv+?V-쬜Ea/d8c'CZ!?/InJ`0C`p2w"\m\ubgsGG=϶;;|t*? t-Z=s!H\rhw~BNJp'0iuGVp:%NE?Fyjnq"D3,>׫Wf_dΜHhn}+{JU2/tj?tfr2氉>P^!͠fMJyFx~d|X+Wev!utS0Qk`ѭ0 6i!sZrMcORnv m7]߁XU?ͩ+aZ۝ze2t;`Qį~mh>8aqx[HO̕Z\;lu;sdXP K aOL_8!{@Gٲ~GzW_wl΢,X˿J1g3HI YP2\nV`ҋn- -`[ nȕG^͖D{N7vX?(ugr}WV&qdxY]x(rK#0'C/Q!EB(~gֈLU؅Ⱥ1 YCigŕTJ`IO7kIwQ租 fmsM%BHpFox*$ = c;D#S;V:EM)V1D ;~|?LÚ\f$,㧒uLm '¨&JGu[ޠ2>N-P Qjǰ/ Yn9J6exa8UdD Sp Xڙ(7;TD?L4ÀQD%VFSd! F@|BF\v*!䀊f#W<Ëg(F_0s%grԫVw`< ~7 &坷q1}}r=;p4!kLxlH턎kN7E^V|N Ȉ<)M2LG,ϩj" uN5S3wo>d:~:-- .DiR-?/j^0q7>]I?ei1Fxo`<RYp3TdWeh$e< |l#B&Cì8T.HJj|TD݉}2  ] g&37Iu+gXwMeNm.DF,z5^!Л'iL=2qsiTA.P9{lzFm"#Ҕ?p7?!XFxiO$k2]g{ˤcPO錈1K+q~miRU@|0G\ f1dН[:8bq ʕ+y ϪL bclA]6sy]TR25E}a' u`\pv~R2$A toNFmOU;s7,>o)9ZHP}OH'<%Iˢ&8T,1L8H2H m,JW*宾%Л>L~L;;_Yv^S&!ICowcd9I/k-?}`QJˈ+QT*+89EʨMS~nQoUo]ôvo˸qOMqΘXyMYp%7 ]Z@iAY6Opdŧ÷)H,$#cӡiEieVٕl4]FtX:87hȪĄsPƵm^T4Zuzhf]w=/遣rYV["/.'E*%kF'hec" %P+w8)$=>mK~PPG4<@ޙ/xHeXv5,bsvk^sbr(@fSYd6r18qEGkS|vxh8t]pP%*V0PW%.( ѦΙ V9鯝iwy.i}=l[6j0M&mެc"oQ2uI<|\3>Ǥ-;sb4iT0=:sL~ =Óy<g/D C:gs䭼 4u[oaNNZ Z)cg!oDAQfP/Rܸxb{J/iit; K۽"GP SeGnAǙہFBA(tkA̬%Vh5kA \Fy{ Yhc=⨺k ?a(%tSZb8ԓܙʷpDU(̟j; ji۪ BnArO~\t!K$8,Dީ]LKm>nPsE1bݠBwv#F&\Z62Q {d2^xʥ4nc3٪<]|>ϗ.-q7LɤhB W6_6SZJo/mЍ=caDD=a5|4^3bo9*&MUϦ@mBBCjI<|Ml1p/v ү apm;n]5#ę˷K\ 6s]"ytWRhe+<TKBx& amDlP7E7V?ɠl ch: yOZh,7lK/[:3ePL)gl\vҭ¯ a f7%nJHNڕۜcq}M܄ʤ\ߟ+,q\,4e{>+ Z:q^a+?_AFl@-~f[!^7??%,ݝWl&(:@uʯh_-hQIfտCeIHN&1'qHT2$ӎ#7D}nIV`ͰY\7xڤLvB7`MJ1-:dBu;/R[g}TP%̦/PTcm3btn5(;i9>P] GEf ;2|ׁV]) bSoZ(~k=WSӨZ>qGE,@+ℜPNJiѩ[ KZ̷'gaTdbqQzUeJ 5Iw]͆!(,?Ju{{txnMtGjEд8KguUo5p~(?%Ę_~Xگ̎wΐ>l`xZ8]5`cT,3 Ԑ!cJ0 rs^؞wF$tʞMcd2 5'Rap3B;:)g ~A]1YAbگ!R~=PXWby# L[b؈"56kc1h:4'I'6AwVMfhbԱܴTI{YmMzٵ}Al$)UuMt&XKqh2/ӫ\ͣ^W.)͛XӼ)gBMӢO[D=+*HZU0+ɧhjnA]FM#ewQUB %YMzg/:?H;y2Q9t(xch*5ч\#PIu((oIūan+}!wg y.*=Ң=U$6կ:(4xo F<&s7C2݈$~sz7'X Qy]u2"CeЈǍ)PelI:8G<7f6~틬z]?Gp6ێO9tQaNN]0/NJ*rtaUij Ո, ngf&Uj7"9=7@9aa p)ij3Y.-ʍo'#N-\x rjb7Gz%C1$SӤfq見mKd[>= U4z>t w [`AxK{.Lp46)0=7x:I&^; sMh_>h ?_#1"W+7xbFܗi\< mj."Թk JI9"|~u6>y VgKpZ=%E_$13+&zfm| o~㔀P) [(oJ_y2J.w \~ώz,Hbߙ q c/\qkWeMGF$W*ks:"'͛ _\Hz|wWULVj7 $M*E9{FN7;qoڔ0+ 1ȉZe 6L_IlSV$⊴c#MF/%:",EV݅τ_3rI7]UsQ-zc j1j~^k'S'­B&`RckJ'%0CBD'( ^nْu0Ҟ,߈&K# *Li|fSn-KKICg<*%dqUaLpF 7 GצF?}H.<@#"D2Kp2l06܂?3š@Zđ&+n8jMwm%{=cn'"۸ .VsJ}BxN}^>CI~Ap9(1e|UibN\Ϟ/m* yÒ#Gfn麢iY@(2Ou Nas ` Rr'Oˣ^cVw*JP5^\.)r[ܹ(_~R8wڴ9(6%V ^&ޱYKBeWlX;?x(3$y r/T/Ya{a,"EKܛrY><jӮ zNR~ 7@e7ikrƛ~J~ 0Ir{ptjf > {+ H_0f|`؁8@'ɀәޝ1 |S_pN"rqnF뀭N937;gM[T 0D>}D#dyG:Gi-=.ի'[=!>H.)R 'ʵзl "3ۈ Rςeֹ{ !eUVXСx ׊Uk4nQ:SSΨ2uK֋ܐ#̖/8aiD>`8Ė&s.ǀ6yWksߢ%.LϖZEG"JdqrVn^&GC$-+P]j QI.xWdc\|HRS65z'[22y,< 4kUODr vl&( eck# շ"?_ bm ̒bfݹfyB̺f(`.'ZFGJ20I\TFy@MF@&FAם5Ý.IRPHJ6~we=}1ne 5v+mueGM&3XOQ/0s$)5'&Ow;6ei(~Y)B'% - ro۟[U9V0eC`y9.,Al8tَJS{ۣUF]fK0%%VUyR[Rdع_%DS$ PD3ئV6ra=nB,Ԃp7uD=:GQ~KL6}e3Q៞b{yl$%K"C|D#ef_z껜^5[S*罿Civٮ^F5i4}W}^{?@QJL(L1dpVVju^_Ly 9.Xgڍ{aWzj"?~>okH!2YM0s<6')ĺehN}^Cy>q itU? 2GW;kꡤB sׁ:qug46!e;I$?2mԉnCmϹ_O :Ղt< c4h"16[+]}|rу7``N RRA.[pvD#^J)M6"}{9(wwh wJlyL1^-J[<@mF0p!Ihzf[W<پUQ> 2x\(3|*OhPS,2o!׈[T'"o gI~C9;^=#t}%7A,5S%dF>c,)kk|8wi@&܂vOߕZI̺{w g!=#M}Js11qGW{٦BX&"iGǖ,zPT s@ʸH<4n\t(6q70j󵡖 pE% S]9!(׹$ sV"sFx|-mo'O^4n'bV"B>HA o:GƸuhU_\M J`!slqu0}Mav*m8TCb('2mU%1gz.O`-H,s%cInƁ KhR=y3Zì$]dR4DA"/CBAG퍗E,Ų/ف>CLϠVRTH,"ˎz~7[#8BCs̄0瞽EgH2[-:2o+7`n7? ί|p)NV߱6(=W~6<7IMP6]ڒݴCL1u6^V]=KEejx6!~ %ly 9-KiҮj=n.b/<9R/-_E^aڵkteIBA\;+ͨ"ErLP"#6R}zﺞzl+Y}R!xVFmD[4ts &WmhzP#MV Xۑ2쮎x2%ItK:,^4((:#UC\Jv)I4g%ʼѳ` $p#"b!\X|1enq,YV2Բoz;+Eh3VHyۧt 6Xud>*mSFz>2O]`id.L}ұ ,jEہD߱^g*q侖Zru#u{A|U’T4H$ f!,:EgٻO^̅qJbrijÌE!#["#ӳwA?nb금 О!5{oQRQr@|c-PS2&Mz atX#Vā E͍/]jl(pڱJ;d%琀L6d̷81=:Bם]R1#߃ tO18Q}']:˟ڀ&!DC'Hh,l>e+Nseޜc;"v>Pɥ2*m~g#LۄȗB;|n:45,&DR `z@:q~vk b][jxwRO}ԏ4+eߑx5 ]#dԠ` bXIPX7ػW)k3X vl%tmn@-nuIL lq.ţnZ@2dŠ0m\0_X7$nŕij)+Ursl+s}rY0D˸6[ZY|׷J\W1qbrVs,HusߢG`T._9qYx:0pi3E(%4]P seȻ|ؚ1waǐ -b+is:{XjK̾a}ՠ [&tT"8Sڭ~ƣl¸ˢаD֑ޭhOں&^dAzgsqYŤX<) KIaǥYpE4D) h:^Nnz2z{+2{o1V=ܖި/-UxL'tG@NWϢcN51zp5,*=;3Liak1Z4CNQΠP1 hc2s9ƴ41{& A%7wj12l#7UF)Rrxa[+KTMGL^]dR.)ۈr#מ,lo&!]Y'ɩs6 #b܃ ukPK3-[o,=P,D <[6]59i%ʡ>nOؤZfQIfZ  ,s"DKW[OI*!s,eo7Z4;"Yr:n|hgW{W7| BJuh&ݭ;= M&j]%tU Rw-6cАds< c" =aɠ/ŬUDJ 1qW؛LP(*15;A|QkFUP^%MOl X,(NfhI aaЀN~Xq=k VhX6ek5]xV$F2O d &}OlR2IHR4#`Z-v9LD[X<^#Vam- of4qE21| g\Tq%v'Z Zx q?=g +Cvm^UcLs>9Ȋc@n9S fG.b3U/Àlg#M v8T0; 8'd4Dզ@8Ъ.&ve\h X};n;OM]դ'%5PgEgN{d; ֨=,I  fuMKVaq9xNH􃅷^*< E3c4/Nٽ!n"086@uNKb+g{lSi.&f2xbNi;Oe_s<ٍFZ>6Sc&A"j ԍyprRqb]&yS|9. o"FN |Q0k=4[} c~kКI5HhBedk&WQOmXDVfIv@RizU0>{t80̀X-MsD#75aȞﮫ)g.i0hYQA.Cse2vb*i;s>HbJ k8",nsD"UWmTҕIQ n{KXIl}_=lÙ i@][Rt $P,lQt(Xm&U $S}-o7{*&2}Qd!diiP(@GPB@# m!:a PUk], C!Tc;B1b(e 'Yoֻ핏t7BCOjq;ͤW+fڝѕ6_㞝'NTާpi"?l-Š"HZȢ dlZ)ΰo"[cLF(>ERV7;Y`vٻoR]Tfp܍myh9Fb+KR?fͱ;&^{* 8,˅pxŸn !Z]q*oYV(*ׯ&:~ :CLzYZ.R|}n<:ywt:51 Kx]b;g1$&v/ F@.ykjMtWnuŻma?Q2J. AuT@4E}N/[):5ػ"{3צqW*I}`#.'_Bp,w4ݓn-C pn%.J{r 'mVŻYJlačX<տܰh X늷o´MYVdy g߯wK18XO\"W~ GPyПm _ .s81 3VV~#{hP겚S0Us`\$a(_tHՄ"CXzWJ.g&AbM"܊/8rƍ;YňI_.4L,^X%?-pNGɛ Lx OS]ёy;JW.%YKVeFzխ4b۰%;b >14oKj) ,rhhk%,@j 7/3%M?G.idW掹y (gdG&S뤺}`ˏ 1kfq?}X K?{ʥ'M?U%fY>A+HTOC܋?;cM#- (ez,Nh꤄ ,q"Yt\9H3p`[dsFjjE^Ĝ% yܕX$:=t$)N;X\  FAGBCk|JD(C/]dۼ͐+zWZOQPޅ¹C yP!xc;;Fօr7sv/cl*¬c:Jo{aȴ}2I#B6HVQ?h,l3`$lΑ086nZɹ}Fܜ@[^< ێh^︋,dI+> endobj 3211 0 obj << /Length1 1414 /Length2 6355 /Length3 0 /Length 7308 /Filter /FlateDecode >> stream xڍtT .! !9H! 9A 3 30P)tJ)!TD:D1wݻֽkzݽqCQ0+*!Th$$@(Ig"`d|V0T_{c/PH' !US@ߎ("@ ($̃O]e~B r7~a8.0ˊ0`aXTrbъb`w1YEu`0 ` vF&Fp{֛` p@!0e' . &ho?HI'ݟ蟉_`#}Hgaq0@]ƃpW`| <zy?!Ls9em$TCb=~ cY7$Gp#N?A@=H}OK?:g "3(S} B.AN?2? x `0g8jor8px= ?o􂢐W@Odb*l(OTJ *)#Pc5'> P rv ?#wc%a(\>$+FY_t<_f_ v#|8\2{yF@5%pOcסtFgp85c!.).#H)[vyo~`H $ed` C O@0/fŐ(e^ !Q98q?ĥ%(<_o`8lv ZqR-Zyo:CHoyFI*T9RO}CnU[PmߧȶoIv7ş9HE-6 v#l2˿)OiZHwݧﯘZ7ۨE~^1.g{/t1-ub(Uaگ8ã ڼ .$qR%~w%O.˫$d0s!{e"9)֝ B^-7(P:hsvwήZ~7?k;嵵*zB tmx@YSC7kRE2px)fgJ5֭"ʪl&;J_aYq^,_>T$! reēQ͊"mAT}g=#wlDJbTƈGtwrM w& ez(j&Cv ҾĒ~J+.)άMvVxtM;/M-WV U.jgޡ?pJ[$ *>yXއ]܉Jzo祝E0; < I#; egS q }0?)$e>|-UI`Ћ7dy_a[DG𾝱WQSl.un_9wgKq2D7)F\BJ/cx}7p Q1_X(n9v]ft\vG\$|v-ݴR'p/)vrf:=&_aT9zݘ>.gUf8n<†?yu1VܻU ~,i;}B?EXdWf Zc׹lEZ2OE>Bl5ǯ&;}vԟԍ٭5W8'*0fʈmSEBc)6ލ}u\WxPf Cs!kmCA 8^jJè`#AkɏFacy x /[* (4(Vc UO t2=bWZI_i[dRwvM w&"VeeZ_ ́W |Dz |.ii)"g˵{Y}4Oo9 [P4 VRʀfDv j?n-HV/hΏ!mXț]1SȞlHVA\V_deWTfY}kQ$h#gWĝ| -ᵪd vvwևM1}v1 J?򕛙@crWm"t%*~AS"YC\k,R#7+i"'|kstQQ /'1=; Q"pS=O;Վy wȎfw2,|z'Vmp˨RZDa6}wlD"Ԙg'=?rweFe6 w)l3WkAfzYykάv#*i.2E=(L3&$%,+4z,cs<80+ܫVw,vqVNSk *?eَMH2lo=RZ-ΉPBqP œ3f0]j th{WT%/`VrA&k5ݣ WHUmt| >Ma̽ӏBKr<uZ:bYz(;@ Ծ31E)06'yא!1[Fvquk#2PiˇkAξ߮Pa8)(tYVF4\~_60r̿඗tLA1u~%P)j{"3MI1TH+[@g˪[7mqcxnMFM(-Z~?zw[8LL@=kpZ[rw R6%U']/csu H^5 ^a̸*RPW9drg\RjnWZ}@kecVN&u霄'j!X\0r|d}MQ%k̃FMY F AgQ(RϏPJ Q׺8#qF]vdB,>ޙ>uk^I}Vv4'h M\jn̔tJPH9'nǘg[3YMU_\\+mOl ! .2#$_&N6ElնZ]z0[ڻC-lţJaʶ$J| սGWuح\ѷΈQ]x4p'$&.#:jV$r #Gd, 06]C|7%$ +e:WY%/;v5G*O>#"b2}eQ$}bnQ;xsCZZ>>7yuA|U T%,f+k\mI(1y"4|x,= dAG Gz/3Տ>U6 ;g/np!=򭛰Z]dNSx[i7.\{77 ARBR3g΃T4ۖl#-CT;TW 86薚ZF'c꾵PŚ@n(36"]"p[ȡBothyWtݭQr9^+bL5k}*,zl S8ɝonXfHqą{!ZmO>k`Рlu)Ux1u%zp:ddLՒ3<XņLAa8W;MUVW3_T̲uIB.g'9G"&쩆'FTj(ϲnX7Zv^* a |SJɌxzW Q$DIX>Gh8|=! 4H 9? .:?1s^D0syE6QzvdTo(EHf2_LJ_ ƙK}=^U+LG+ʅk >n8\\)ٔbfXY/WW~qAd}:w=Wq{C[{Oc =*_+bmd'a6'>#9ۂ ۝kQ}ǞDLj<tD+f3 _znve5$7{rhͧE%#,Ѓ" ٛHL V2Q9%`ZWNn$ hU^N兯4r4Eُ6׭^[("9}=T;MeqFוv[ͭA[fPXl[Xpƪu#6`kGqĨ}6+%w;fa;ͯEŶ7 )OЬH[y-8DcB4yLFC3 W^KmN|75:IJ-WSߔ0:u~t|Yq'꘽ vf}Ц=&> l< su[9%`ϮG æOy|f6Ҝ68']{b*8qO(蹅iJ)i¿ow(rMb > 5t-4G_Ud܍͸'\ES:93n W77^4.kN~vVҔ+7|gZ2RQjciН;żMձeQ72^#QmK\٭Y__,PAۂ&|5k #T}Ļ6D-xIܒ$ճTC6Y@cN4[iB'ή )HG SRjx n3IJUuC=F 6wAR+g"ơO{Ȓj&*x=q8Dc 3Cl?[TdZ9cP!nyVưHF헻Z:>u8M~;]R*_~2ȒByi\+`ymĎa_90Fn5$ %]TH߱y(g9yFhRCc6ٻSx y|aU4٭T|Q{{Ӂo Cł3E:cپq^*.4^,A2{: 2m84ɦ&Fqff}5M9֍l~I37Ͱ?VsVYqlMh&5p6: ~+\INܠ1EVvX<{VpU7J*d8ogl 16} Tzr VOzi Si]r5CLpehw:>WN t˟,XsB$ 8fR-Y$ߠVQ : e6 w n$/0dR+jlN@edHrAuv}oר5GJǩ-Nac?$8M<9vcK5 F~=Mg?Ks%u Mgd`;@UyM!mʟA#}"Gv,ڧP.7RA_́NU>Sfx絺3<=E d^|cwO]r+(Lr_l',U5F-};û M-?|վ| Y0uv_ fԣJKl>,Lwm7Uw6Y0T $Df?_2Vcn¸ ) f!cg W&>[MRȼ :鮏Q^kcP73B@U# q ,OiBԧWSYYe %󡫱e W$"tU|HZG+t(Dojm=k6AhLY@ǧmƛ_rRnK/ *[ endstream endobj 3212 0 obj << /Type /FontDescriptor /FontName /JHEROP+CMR12 /Flags 4 /FontBBox [-34 -251 988 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 65 /XHeight 431 /CharSet (/a/d/n) /FontFile 3211 0 R >> endobj 3213 0 obj << /Length1 1447 /Length2 6643 /Length3 0 /Length 7616 /Filter /FlateDecode >> stream xڍvT>%1FZ&4 ))5ƀ#H(% H("% R]J*!7}sy;z~xn);!aHF, KA 1aHc x@<07*05禇D}<`1 XR,% EA hYj#0o*bpB`)@eO z+w"4AB0LRʹb0(Y???a0'c\0oE&& ½M?p( A8@@-] YAW NgDp`DAp h c1@#BG!@ e# OvP4{b(+ NHOO U n=@w[H?3J i遃`.0 PIɀ0/ *+i Ƣ(3, _c :#Ü:pA>lqrB"<q\K}5s5߄6 X!Q)pg_ɨpFeh ?Dž8À$giWE]o+/cx=TM7v1z0'[0d(#\Y:+!o& xQk@'TN3)IPۮ+3m]. p3?+ُJhwעa7iM]I.z9I|I9ZX Ʀ8l=~].oB{c+\}TnD?S'ΧxL[Y!J=mgtw١%UČIbMEaTKMai8q]g=WW{|Ԝ#0[8Sg- ]dŁY?/X.H1ke*𰞭ߚZ1M+ abU!G4nO߹402zN[5t⤼d\'bYfo,=dsαOߖJYr5|duƓ;r~|v Ңԯ`nJQ+3N(THH+l5oaibysg2Ns3Z6Ǣ &٘jS]}e#ǺO>_ c|gdv_k|+H Mb_-j-e=Y/IOF'Uۊ7$"wn }M8x5K?$.(k0\G(bX ՚FQ iPNv!6`k bȆV# yeh@t-.-Sv(UNo"<[4L;W?t+ ?( {sVx6WH"bDWPKEOUzjl?=I.-l#3 4YS4&QjrGuGJ[#ZClS;*gl3! Uݒ'5Ia+nf/)Ow(lYu|F. _LsY6IyY 4G)l.挭^̻gUpTd4(c3pΩ6s5MrgcM̗b)IJ^y۟r\B!~TS&H22[זϔ8TE=]{ HTa\oTN2S+b^+4faoC{7AqNfQ^OD_(?X3o# [F~&<,<هNUcXtc--?Q$C["[HnwJ(.l k39 M1cO}q:U^z!+we94UCeipSYmDY?dNS( mdyN ȗw!6tJLqֿj2sZ}2s'E8FcS0z**$;=de(CwQ Mydž;jx4.(C h{ 9Wz&v+KlMUMp f{3ODw=Cwz5,EC 2oO'6%A78`lm.*' }Ћq/5L>LqT*)!Gl #c3~bt3Yi|ƖT\5ǹ2ſ[pr\#fB"5B_-m;=d;eb:*oeM *N4Ps>ZXcQVڋ†#,X|FF9WʶcA7R;W%Y3Hw;Ǟq1Ի+Wl*vG*zPqzR }3:q? *{}/! W])P[/q1@ol݈Iu}YF880LF[xZhq8뱐bXn~jL`n; )K|w֥ѝ7UEuۓ>(:t~$إX*TEs'i}:wdA$pVZu#kt ZLӲS }!GEk5Gc UWU5;]3+Cָ,?H v̍ʫ{+V\.|#zkC\z*Vs>l"5jg4a)8s$FF1oYx1}JLjrnFw2 Loj$;Q{UkO = }zSFAi*|K÷S]e~1[:<G|e-} ՙޟ1Vw橓47':F *t® hL Lo^~:ka}"fD{:j>?a%8%pFaqw[cX[M:6YF l D֘Qgu|}nGTjgT'qŭi|+7݃9y>ߒAzt+ɐSu!ɿAv,z=ZK\Nްjtm¯K3A0 XO5Ͻ1D^޿L](l;l3^Je 88r$6jMmmr̋ݎn2poG~N@g7,<>%/һvmoxB̵nFϛ֮a$I*+kJ(Vqtv^n'</HPnoߺmzCGx]J 8H#)N?I-͝t[]9X%Y]1+bcۅD:{U$SjBWGX k̑CxlL u$p7Ꭲc%-0a#ݵ+C Ƕ$ ?KFQ}-ᬿ{'W϶PYJN e>ĻbI9w%EVw8/FD4ēַ#k%Ko K,cwOJhY)/ЛCbƵ>% >lCXBSǁP{2Hdx-5-k-ِ٫;EZFcgr\N][*Q Ub헮;J4mf>[ N :Z֯7xUύT婙Z̀ڐU$Or`P&Q"/.zkT,0 31 (^YU) $HmBS:Pe5q2B1:{ޭdJz'=fe)OXkg{|'~LR,tϹ1AJJ݈X%6=+/|}=g?&Zn#t膵ŕӗ8 =S %lT9iΏ= M?4[#=7W68;+@$T$k=\SwDr鞲-qͳ_x.:qT$rӂ`cRYYU^m?h6K3>پJ J\7œg?rj$ҨsW]kK8e2k9a /K X 7ekXRi!@ STh<匥x2Z̸"lܘ%Q 5~yܗgkmkBTäynӞw'_$ EDBJ=ًjH*Z WCN3e3~:x J}։q+(|҆ȟL]!c{%c~7CX4Pz3\h)yc8yOLR(ΣdD1lw"(~>-atDFOrdr:׏SNPwrpQ)XڎIpLpnB%L-yBO6,9ƠO%xoI)caQuÑn}|\DZP;x!LЋ]r Rz.q rvFx34L `Qts- d]wZ9sE_\+FWt]ՔƆN4ΊZ4$]~ÛIwp}oY3M0%mwUv3d LkܲjO B@J‚lMuYN)$9n]Iy M R&',qUʃiMQ@Sf2% mWJ0j)Ofӟ4< 7ސݾ))i:` >ZC,x=?0DJ5\ckKH}H.NǕc.hǛ-oJwX|uJw"l:6%fQv;;eAm19=^5z:⫽]'fC4N>Ɲ3iō|9\@iPnό@R9 w!骨B6E#TsLVlʏ~?CA6Ǫ MOW}7iMֵ"ש${. WVc2pΖMV#W7˸bMZ7X뱏 UYHRy5>j-GK62<~Xb] ,=75Nv;ؑ{8=|&jTGf.5lҟ =-Y=|2`̱TP/qcco3^Qw[VLhBe"ml/$0^3N2Ѐ)an#:Co.yPe󛊜6ҕ_> f rRUv\Sp#!'\9~cz+uAץ$?uQ 3W̟/]֣y endstream endobj 181 0 obj /XNDOVD+CMR7 endobj 167 0 obj << /Type /FontDescriptor /FontName /XNDOVD+CMR7 /Flags 4 /FontBBox [-27 -250 1122 750] /Ascent 750 /CapHeight 750 /Descent -250 /ItalicAngle 0 /StemV 79 /CharSet (/five/four/one/three/two) /FontFile 3213 0 R >> endobj 3214 0 obj << /Length1 2626 /Length2 13789 /Length3 0 /Length 15277 /Filter /FlateDecode >> stream xڍT6Lwt ) Cw7] JJI7 ݠ |l=5k1sq< 5* HޕWUe@vf Z9 1g+X&n 6wȸX\||@ 3@ q Q98z9[YX'֔;@lejl7vف#TL@^EA+`lll!Dr\@ 3 vJcFYZPu0w0v[+S GJAm9VfEdePcvteۛ24uq[ J ) 0WO}.V..VjdEnW~V Sp߽X2Y@؀EHe W'@N%˯j^|2@~V ;S`fe 0YX#fAc<@>ooF"#.-.)O*EE<>L\&6N  o*[޿k7?u:GPp3@{@S3bnf$fko :&,2r_1[H+I+O[9mAJ.Vn+?:3*.i7u0u8^H@qr|X rX\.py~sg_3,7E7F7"X~#6߈"q7"sF\~#p."p.J8oF8濈#pt_ ֙:؂ /o_sf1 fV g m"7/o701T~8$5Lcnn/쿠;96 p6Ã;Ip--AXeWk7`W"ofN=$w2`gRs9 ߭`G_ar9r%r=opm5!7_¿[K 23\9~+'4-f5? n\8!Qϭce;gqt2.z8p'>=`z? 1޿3y_3x`=_, 'ii?sHCfGdv+B|ԴY%HbyԼ/ø^ԷۢLC߯-@fiۘ$F04B{~v%wD"9PTzqXκnj?Eb{me 6a?@2 [bs.P-*3򍊙`[ԁ*'rRT>!I<$n䯥nxcp[ct6#‰uRV/}3ܗ9*, 8lLȂ|RtAn^kh9JعI>t{H߸B#;򑰶6>xGq&|v] ['nMq7ވkAKkװ@F)6ULFq[@] .òwVl_cK A4LW7Н=RmeXG6XX۸T1ejF*X0:x7x&LGm8g@Bo{lj*G>+wlHT`z pL :hG7fĐY mF6mpzB2T$"y]Qj6ѱ;T6C[ݫ~3]r@e{II' nm% "elN?q6Lp t@$} "r^9X!@m+<P⥮¨%>Sg9)hʆ8qq[, 5e!'UYKW`)eМb(AEMHik3S"ɍ_O,Pc*HKeȝ1aN[If K4 ȵӷUmկ\Uş L$Y7z@'0:唓>S\v/> ೫zRKa^Je0;'-;1Tl+dx%۳@-7WdaLQ@_7aV69KE-jY"utk3MA7Yզ`;E>c= h/`@Ku*@Y{ރge2\*y򡈄ӧtدġk!ldL0ST_m~I6,b&wJhǦeQ<5z:ԦiZL[8ޠaϊ/JK$K)/qbr`r.iR gpLjиm-7g3='mӡa!Lcލ bRP醙sVIܫkLd2c!F{ .^!PiO#26 ?u)7Dq6OyiCP^Fh"~<*ˆn u{de!DgHV'tS+ k[ϝ9bSׯ}tw= l϶hK-A\/N iw'+< p\*I4t 'zn BAiɕf|5Zs'*rkya]HzS~|};mOYB1Pg.լx@%,'`YPŴDL+,|M]pRlxJx{ůD5@QvFBŷSq$kWD?dSvii5_ *ϕa̟=1g{ ՗QoXwJ-#Tr{¹\sɔgq4[Am܁ey` ,Ê96[UPP_jar=mQ";m-õ%*Eq|};>#(a!_TH,~]iwSTܑ4 3v iL*H/g}n-RʭƼ.VH j*C ؠJrʳ=jܹnI̸ . e/kJ㼧Gc=$Ńe&|tMbA.oQ|e",!qn]ųՄ.I [uԫdy͞BxގPƵ}59~cdI{OnQe ?q?[3Y/r, :w%/te*̠2y8KՋ:TL S>. I1Q95=>/yV2 c:"k򚊗eN@˶"!82/gI,BD2&NH O̒g]\^aTR K[uCi#r#8\أMV}X)# lR.=@gMWsi„1#i=uzN.U~y1tQaXI5Kaٰ"T֑ { a'=D"H슞 ~fG܌l4pur-!X ;'",,35Y$u_^IŞg\c;yіg1Ƀ{1V&ؓ  :YS*'%u (! *8t+h'*- 3òʘ78J$lRQ?AjpbmI 4 Mi$ 3 ^y4hb@.3P╘ml^'?>P.MG`4߆%!2?S7aüJ(0^"0WqqhcrCAnnwR|/,I1oo%aU.r%I;=[$+Sj@ztӌ^a9VU2WU3XKFbiG'LEena]“S88Cbiooܠ2ة8+ W< C!]64fi$Ϩ]xZcq\믖W9^mHꗛ:겂VJh׈{Lts+e+)-Be{Xv2ڠSLxNғ:ջ9ҹdeq3ٲ)0窍;EGv&w*x_{mhC?Ӷ:A(ed B`eX&2 óV/=-$rtTt^ՠ7%8J\}cTWS ({ (}Vo4Є,Z\ٷ'9 KIv*C؟"=I fɬ\z)Z+HSh.LGdIv1KxPk>^D} KT0JPdlIk~kR,*4HϢ?RI |Ё1Vף.x[H4'fc_ڐQ䧆娏L> ' rd)PCc(*t-)eGCC`՞fWĢ WO_N/eO.:δ7Cዂ4TT=f>tP~^;qh)KKQ^W3"Ux;1Zs HΖ"v .džf CacG μ%ѓ\ؽ:$IK޽"1LN6 ʏ$nl|f_O5OVJ^_m(s6qnoXٜQHŗP< iM<E)Nha6+$"맕Jh:G>(섭ۻdRxHTVT]bp:Xwxj\ar6Hٴ-ָt%t&,(Uy2P 8 .vooٯ&IaƫuzsSZhz8S0.5}=g݇)Ovc;;G&x[ObVuV<_>Wst.0AZ8qIeBIڅ!l㡍*@$m1u)? 8!Va!s֢~ųT /xGPU)|gd{NpQKoFĪ插G=mWyUi\%PG}>Vkױo٢la}Vtk]:ϣaRz^5 @%,<}3,F0DEp %9&"":UC%mRr^~0}(Q:r*6 S`%ͻ jK4.a\ɣ|Z|5!zt漱nLGKQ| [ ?g;H#tʏ,W( {ҀxqZ k|Hk0@NgSk.1=B#vܣ!0 fn.T1X@itB5c(b|3>1MpS9t}6 \:T*#t_cJX# qD0uL>\1&|؎[ۡNο<s W~taTxVr{ЭZT)'.Qi5Ib]NNIZ>UㅓVYmo葒ѸxW4nT_#~p$]*H4Eh^r/rpaמ*^?3FмM dL%4t2yFņEmf337=0E3Ƅ=K/NdvXpVTzYѝD;!r{2ȗuW*r||"( JfT䆪W-5"I+(KўXW"_˷Gsϭy,jij~H}W Xjaj %;<a5z B[{x.KX`ϓV6Zb))6*r15p^*Bq5Wy-,ڳQlE҄b _9 :?[s&7I9̎|yYł)9ͽFgm.;]EQXc%.7dko;h[Qd̍82B:ַ0җ@f zY>TVsg;!Vs)a@o]#KKn> "uNj*|AKb4 NZ3k ;YG=Fh`TN<24UԬJjLڣ/F; ˈ_ a(q)V}!䲳%%R=RQ: a+qs_qS ϓ\!O"Z۝.T8pm5U+2Ѝ@VbwBe~߀ J?/*G)'Y͔Sp}V;"`9γLهQv~H-o~lSeNl;A6ӂgQ?e6eP@C{ry?C\I5bn[Bs yM鋟G\nJ"]e$S|8L=X4At;Ny~9?Ȕ{G}%} :o&$87bWd@k/e%nRh=Bbg+jZp.SِY2o6 pԘnFU9nOYgU|no:cl_/z cW@gZJ㟹[Ey*LfQƑg=l˃EwKQ ղ׃50.7mWجxeVˉMZJ䮅ܼđe&aD61 OSdnrCd0B:َdBe56r+fTG(vK׮Z'+He"䊆_-m1 LeޛxbIFe΀*(9q^B6kSvLk0W1.CmZ0SyB%K}#Es Y+F>Zyn[D2RK~5Jv<~^;X bI,xu1aEq ph߅EϽղF蹋9 ܪ*co| by|2_$0$Y[q67Vb.p]D%(+MxA+6u@o>ݺwc#&oGH{=nC~jHMꕕI&;L>/DJ y2`daMnCLD I{T?Q+S϶쮽 ZNM{wž> s!.v FS\q=JJSy89;u7r] ms_R\8o$9O1AVlw_p0|ބ_ Xl^=< 1 S* U">jwW8JmHx&wkWPe-Dl[|>e",Cz;pHd6y->KV@ڃ8lC5|fZ[ن_M&SFyr5HW >mPl43Wk`TGZ딗4-&Ȗ=pef'?]"_g0Nd ;KH< kQh1L[t*dnimsOzShM %{3,*MNrԊddqW95EXsM0 OQzhIkf^!ySQEK\IkD1XGY x7;g(_:00ڬzgU/Xa)|cќ!)ҌJLmYIz5%6G= 1Ш2 :PbCtp`L6aY@VYw}+i/6.څ'6/${x*O>}U:I5IeI$nA-XW\8 /:/S${{sgQȐ(ZG!Mv F3|A$A^W[IMUhoNaުwQ?^ 32D2%n^~buJfWMt3Svmw ]ƫWBDn yOk8_M. H2J Cp%sƈ5QZ tQ3BOʎ>\l15$՜Ѧ?Q }b,Q>{] -#𪗋m*W{%K:A~8#ɔ܃,:!*fk[u$B~(j-6=Q1_MC2p˩`$Q3CqҔdl;ܾE_V-W$C?M:pv%S.a/\<%/·da]N7oءB(ɋM + YA-ʔ4y1t<3 (Iu K7zH7[g#pdo^(eqT=LJO~n0T&kqmMTح@oV5e]yn$B{ ˧)mӡsrg:{W33W\BJ,DŽk"!EOB8ֽ_?ttA3(:brRot?؋*B(<"Tm6{7&N_z q$k`8LHwמjjD @~&b?f9$E ѷ!J3Jv(Bn3rc豚']`k` \?ք}s8rJol@4G64ėṞ́R]tЪѹ>s%"v\C! 䲢q|b3!yR^VEOFa92O}Y=, {\H eh/45pq.cϱ'U[Y&ώIJ^$93ޟ V(W^DGpKnA'WwWbRQBQtzfbmm)""cm $Iw3h0 ^ MǂO7 bO) $bБ݂B"Ӹ)?Lғ9jDALy~DxLKcNIt#6IloM%gz2V7 ];ޅ8b❘KcwH2ru$z%Ly#&x Ap+@_ٻ uiR-'uT[o/Kʒfi'D}ihlk#a X1\SޙP4)(-b1ѦK)Ij IŔ 4u7j/+.WY?)* ~(OgBĝā?Nyg!1>Uzic_>0CƝ5[@){E=N`ZFMqC'j=E՝VvBƪx|#oý} ^֏(#e"/+}aQSţVů-aCfMARx(O9Y]d50+rX[ '^W&=Z< h/b$5'qd}Ne5C5iXWuҘR!D{2Usy__ xIHu4I_8 4Qa۫ bL+m9 ^KMyH o7*j٭X+͎$r8 OsU^$4ņ)]єKNnA?i1ez+g;5@\qe&{t{-&!u>Křٲk:taa9aeXZ}jgmo4_(?7/= GZ'1 F]i28x8锢K1lȭUV-ȡ~G͍2kgmu[$DbvWJnwVKFsY6DiAoBIU~7m$j#C`IuJM_dhd3N3y s~c֢jPG1s<CvǢmi5---\wxibφC; Is}YK&5sp#}뺐m"مʒ߲͞caԕ 4Gk-WQIf{1rU˷QLsv⢸\NØ{}G‘eKRjń z*|=vm٬FaV[i|=]7,I~Wu&.TYdBvq_ㅮJ7,VIO{d):LQ@\g'O$ ot~=fV HSW& l$fHt*:g,PXenoJi'ʠ +\i`{tnh,9b6/7h) ״:KdǶ^|](.퓋^IYHMDB/E|*ݒ^LB@D""g!^V' |&g q$$Z.yLc'P}ʁ^֫䆰ӎ{GNl˼ PL^a 5GʼB^ =z>MSuMk*Wh k%320&nrU̻Ynj2,$VLxx#,MF!RDPdVUkڦ."ztўy mf˥l!MrYd: ^?ؙԨ||C#.+Ǭ'G4fҔg>\P5 ,Pj˂)S G7{y:xB)RbWS ]ސ^ r_ыbS\B{aPTp,VT~,N>]Y {[d8©|eص$NV)gSG~/G 0k ĚSЩUŖ}~r T|\jCz&Ƿdb3 s̖^ۜڇ/0KwLeJ]t)ν I>Wj~6Ӡ'UC_=+tۆ{}q$-[aǶ">R1^j?/isLɊTϼi {#iQ+ `q_+ 2c;uT|U&\q+TWfpG1%<7^vqo2v׺I.U` O&.f')tsV6Ic8T4K{*$+nTXC'C~3.9jd9ӚvYYhɂ|#qv}|5}oy vP$=e.뜐5`bg#=aݎԺjN9Ƀ&- HF-v=ON,9\rXJSj${}Qva|y/y㤈zaVsL#|5oAWZΊ4a"R9az)$'oܥBa=t+{ź6ꔁM3g׵nDt~O1Z_  %!ކ6v)g3,1Y 7Iy`ik-z8D&PvS{vg+Fܡm-<}cMpon7wM#݄ejM]q#rj,p@6v'%_-Y5pc>-`_ja|N&5!QG x%I*/Զw&_\5U_}ߘ~pz|DU1x<&6#tF|⸮ -.}R/xEhY8- ύPPU8m.S ć0#xJ$nF_gb%o+{v +/]THw XY۰B^=w|$+QKʥ T dڪ ӧ~-ЛH,ժm+(ǧ(-ũ?V&F5TH/FB4K8:4pTq q6:\ӌv3w3`1[Cu:a+AY.yr3`縪rF*cIC>w(rXPK%~{:N'eCVO!m;Q@ `sl.4ܔ,}On kNKُ1*"9yM)6U!)Bl>}3{mCc%_!:![ӳc` endstream endobj 137 0 obj /JDIDFF+CMSS10 endobj 132 0 obj << /Type /FontDescriptor /FontName /JDIDFF+CMSS10 /Flags 4 /FontBBox [-61 -250 999 759] /Ascent 759 /CapHeight 759 /Descent -250 /ItalicAngle 0 /StemV 78 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/W/a/b/c/colon/comma/d/dieresis/e/eight/emdash/equal/exclam/f/ffi/fi/five/four/g/grave/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/percent/period/plus/q/question/quotedblleft/quotedblright/quoteright/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 3214 0 R >> endobj 3215 0 obj << /Length1 1791 /Length2 8703 /Length3 0 /Length 9827 /Filter /FlateDecode >> stream xڍTl6L(tH7,.KtJKK#( ( % 9wvkf랙M)H sps2j::< b`Ý@۱@n00"/ZD5(p s  Po"M kq A#l`# r[[Bjp{3@j YwtqBY`=@yl$-AIbڃa:tpOK7ap[ 0D;@T(4\@?ɪ]tEJlim uvx!v[! ,!6N0("di qtK/}0k7  ;+ 62Pggu>Yq\5l_2l]C %ٿ8og+em '/3B `ۂ_X0K`@v`3O ` D7/SĄ@!N޿@]G[N/8^_~7@H@ 'o.oX5-; S`05,VP"`=&@>57_O$Oo vgw8b5Ԡ/U>lU["VD bEa`/&nmDz'0 8n |vD*0Dp;ߒrkͯXYzcFl pqBpD!` uS KO R\ !o$Lb踬NI[~) yl 7 @&!Epقp"8 "Nr#H{r t ~u.Czb*w~;-QJ[%y)2MV_b :4ߙLq|Dɷh)7Sm#VP & >) {Kl}*r#ܪT5nC#oqO&@]K`O/_eCg'6F:Q7e+D)20KҔ)PfT1CƠF'-]xO/MmO,.9+[6>? j3շ<^]iR<уqewǻD8Y^٘Hs`L|W(]*+N˟bpD)1szW$,6v{pܖ1Jg8?%$3>PK}Ң!Iλjԯtcqv`C{lF7n)+xe#utU(L_x ƿ3>C?^(=F^ag"a6`9;ԉ{m~:a]D`ˢyMft"Pmc"shXd$W‚df GOvGIgݝۍ^zg HPtl8 b_Ԕ`$ )2"p8toRoYkddX%OyiiMNĠOEz\yvg|VƇh{QRKhKlHP5 >UJ#뛥^хLwM zF}mp RO,N)n͆|LP +0rIiofFb!:MT'C}ۭu&?k;J(^!3 (2XXiFqAfJK6r)g{KhήbMR2D_]ʎ˯d޺Yʕfl=9*0„;׭_bE4Yꍍ!ٷhû}4GOv_& n"C '<|rky i]?yUT֑0\س2&ҖHޏz&a5[èVxU5O_f)oA o\QߊQwuuH :5n(72;0t?옱vD~޿nL騦TPK I9Gfy@#J`%GFb{}16jaAr_8͝’W,s=vW38I3꾬1S]ڇX=N35lqĞ[_- LࡘiooryGrPUB4)-wۃly\VI^c0WKUX(vȰ)WaohT?d.ṿLR]%߄lKzYN"W E[a'qpDL 7 '֒j(L(qe6"oG` ٷ{)4O~|ɓ_Udt&}YPZah'3ۑݿnr uٌΪ4䊒wn}:7P׶L9ٗWdJ.+*GËsyw2׷L>S;low.D>]^Vsx Rq{L oMc[Q cǏ-p_D!{5@SJj[ik:h!S+ Glke`K=f LG8nXpeV.TR7jTj7cTfL2[-%v1ڂ!VOq _'X;`kȕ@3I<4u1LvDX:Y>P/:YW; ˳=F8\6 HEUZx*'%Pc Z9e7269 ȩA#ژF&\꡶ WsxO|tA*#. xay6JzkG#gw޹,MnJ^:?2Ј(W'C_?ޖWRX>P*"Z\@"4||TY0<.Ղ=ss"ŷ*eɾMy8 >_yoEc!~}VoU% v>ƉgMީ /q[T*BUNt?UJRB szVy; nЏQΓ>4\rsi]<"CGPhPFGRvԐ(=wRyX?z5Fš%:ܫK Ez\8=: j?/Cth㢮\8HS4=·\U^9&ݨ36^3ѕ=]*M;@։iK+Rj̷#{g-0*x+g֬ *]X*OZ@%s=0#qÑ]0 \R`%5+g4lY'Dh#*Ǭ;:fl dkѸUl$># 2&{MA=gI|]ؙQ'x0Ɍ3>ްM+󘬪 {u`^'(ԯ#kDI0cgf3>O(0?~XBUR*47<ρ/)8MI#lw$ ]A:cN^cL1] ؖ){\z>(.E=x7."ͱNuq}E y[Bl1!ZZI>rH b.FQbJ̍od6,>(9fl|^ޥ {MUs*?Ŷ$99;2xەl:9]cN?1G'.B.H|pN'XX Lu,AjK̷k+68.ul(D(ΜE3x]Í廄Ws+KO 'a2L2g4LR9>]i0cY/ii|[G*7%mNwuY}M+BK%|j$D)vϑ٠TI(- zۂ#+T吢ڷ-|1l]@\Px|6$>X(jUG)#ߗ !"RY͙J7bNʢ6{X{ 1rǎ$]̞}WΆ 7i$1b]qe6Ž`?-bp{/ۮÒ0Ъ$E a_mr(XդS09ðV'|?*c A?v,#Sܻ%A9`]\A۸wo=u{2\oBT[Ln {+\ي}?tP"j?vjn<ջ O|Ȋ4H~UH֬O$^h|4p({} )2 ҝ b44ec Y9؎&P^HVb?xt"MF.3X`U m֝{䤣 旳۫'kTTlRzr~6&Lu2 8IzONGI6Ij?^Fm/wics* `/6s/Cj!M?IHՉuu0 ZWz [ t oyy%?e -!j OXQxYBv,7 Ia~>h륵kE⎯B)2PyMvo!fMvjilΨﱰ{M] H6.-*-XF5&>k3>Xj]&B:[$"aP PݯV0&e=E5IWl6_Tkbf9j\AǃP>D1B[Ͳ; E15̘4@NS%eǔ:Wbead&F08.@CZ rYAh_$G빭OvB̾𿘓ܮGY$x: pEQv0a~753(˙='>=I^elbSV>'= [͕8D<=j2^()AYGV6L-t7SZ4 #=~&f-0^n{m@Iu$7{,INnLnq-d#8b*f`M$ o3y0`駂f Ss.?~qGa1ѽ:>* qJ\8m#E<{™Jbd+Tjz~._ H5Fگ fPq۞) K I"V܇Dj"d?%$p`Rmk6?Ÿn4\.t6>!u^2)X J/bM c?2mgkW^ [&?L.!;}nѾ]AId vec`^\甆+u.JCOS yLwW\Xc4%az{OϼZ?Y2A,Fe:>?1k8wEq zΒȪ$xޢPțsjkG fJ\1GϹsZ;[-T5jIF+cTe_lPEf*A~>2b)a7^KIäp~I޸?\Y DScpy3aG /2ﷅʂ#o=䆂Ftl%?ǩ:?]úVk;f!c{7o")*V.ojD%_ Ga)HQ(l[:OD<-&A&{ӰoRl~F=rҵ–PhiTLM6e]fTs!$٢0-{^~~t)*u\9IۘJ6( eL'lhط=s C&|hXQq BD獕w/]>໢ذw7axVLJ xZBRyɆo-`k~{pdH܂e1KE .9:ؖ^cp2k[5rO Xc, $!N{'"$ yod*{sK nYř΅$q4b1kx٭iKvLJ1HKKpOo|]Ce"Q acAxݯ>B#.1mG 8-GQC:[Jvm:Yf #G‐r4Qtcgh3ө1o.nΊ[@.;6 2b(Ԃ|HUӅYog_8!9Jp8u:+UnC$,3Х,yE':.14 ,<7J"t~۔C87CHCLb= 9ZNs1ˤ`$I+nT 9MP(qx4:-nQ{~EɌ3,q<ܸQVcFtoI_ ivw 6 endstream endobj 3216 0 obj << /Type /FontDescriptor /FontName /XNSREL+CMSS12 /Flags 4 /FontBBox [-62 -251 978 758] /Ascent 694 /CapHeight 694 /Descent -194 /ItalicAngle 0 /StemV 76 /XHeight 444 /CharSet (/F/G/O/a/b/c/colon/d/dieresis/e/fi/i/l/m/n/o/one/p/parenleft/parenright/plus/r/s/t/two/u) /FontFile 3215 0 R >> endobj 3217 0 obj << /Length1 1516 /Length2 6870 /Length3 0 /Length 7876 /Filter /FlateDecode >> stream xڍwTTm6%J7T!$`bA;D%iQRBCzu֚sv׾f-]nik%TGr꺺^^^^~lff=YCA A [?uPqw>a1>1^^W/G Y< ufE8{l퐷eج>QQဴf鶢EXH`C"@ OOOV !j  h@ f`nu6HO+U8¬pw5-*Pj8p;ݟѿ࿃!VV'gl`P@SA p_G7m<sX:>9P f sFAJsey, Ga:juvou#< 60/ 0UVxyyPee^[} ܂l/l_7@C}o Y!K- O[5v0/{|/[zY#/H>dd^// "|݀jA`p OZ2+h n  y~x+F>o3oc8t;v-oW;U ]im)Z0k ap xyvpV~p+ oJB/ZC~S?`p5_5Aֿt|"?[%!]V Y9;!n|i '- - 2iY%Mɽ6"Ψ+\2Nn⨋uEtI?jݟC^&mYA )JH}޳mP:kg+D{ڴƬ"믮Z6~' )h霖ohF L>#bW4w=e+HX̩LSqLz|O֧T|Վ7I(I}Tr)TPXdNdKK?NEbO<-׏7е>c(ZO ~ ˭@ؽu&ѐC#5Wa2s{-+iRKYK}&Å(%:աBRӥ+0gx -neI'o,9ٓc{=V1N wtx nl";<;NwvM9Or@ 6,Ҥ1Ua{,VyEP+?D5Z?ajNbWSK6d)_ /Y2撞 KP~}FI!G0qG#>՜ͯ"di6+*X@t]b vJzǷu $Ơ*Xro+ m'o-yJGDأ"i0LN6.<;IsgEꁯF3%P6m\e8CaQK>51P)|C9W&T}oaa·2nl>|ΙSc&Xw=r"O:9&Z<=D5N̙b[4|i/xge_(9S5a >j(WJfy]lqϹ6}1, 䲂j <;{C\be@4BQ5F'2||L򦭡 ~z^yjORn_ۻ9oe _&4 Yo\ DG҉whBH3#"FA zzէA6o*OCCZ`ؚ_j)i5U&BbG&p{=~ЊL1^TB=Q/gfm ŕ$SWs>Ό 4\ueRW%d֩V, g,m/i}FNzZ@dTx=B::H,'tG\0 j8"\en|;zDY.^=(+IFk<fH0:, ЖtIol ǧ6ڠDSKzxe DDXc3#WNdp,@W'S)Fpw[=sG䕕ԋd:dU/_7?{ .PJ'ݟ 57k+Oʓ_zvEcsmEZo5hFO}N6lF.@ rك2Z~_ vq΃vP˯0.nT-Mp.a%uޜ\qB6yWv\B#I ċJ~vL W/rxj[Xs~ʜL@*Gpë*VR 6()e .j:O}`0]ᬃQ36%cO]bRDžɷ)gYXٚ щ=F}d%[O30qֹɮM>1_ʵqޫ #3Bd¶m"m$ց0/4-{T=Z}RgsjpΫ"r!A#P&(&("r>|| ⎣beziCLX{i%oh}*#O)ƢT^?^w>jm"%uQzSWv=rN4g¯5U%D2_po4NwVܵ/oG>ri'E1Va"VddY_AtK1|-H*G}Щ^yyld?wz^>$ORw#, ێv+sީBȉiOc|װؽٯYqbYVuGt}תːs icDO~+ͫB0N@/ {ƫ.4S:||&P_b0msIb%]墣G ,j7x ks4ZWȎyS9lzYAEC}C )|ܵ%X;[fٵ C[ bK>{O JE9ةRYA0vQ?w %R-mv³iQRR7:,;{ 'd\|#_h>5ѕbKVJ0tH 񹽫U!ʷvuzuy!R'ac*AlTjrNzn,CW<X@qwy-ZM520{mpS+B~޵8Nu|oBݵGJ/A:GYIL@oFJ;DZO* ֏>8}J9.)^;3oʨ?ZUsպctiBD.fc wH9`woQ!\_V⛸hWG ( t=:A35+#&2>=tTǑ]xRFFNr~T**zASl\j<2IdnNu iϱޚXL"4o{"Fu` 1.)>gJOZdfe8|*˛dC'ʙ*BkoISjvAƝ .#]¢,HF\?(\.U9[}$ɱ1C|8 pIY6P؊EI_% ߰1.uv OP"75;N-M4?/f%߁=i]\ , c`+DeK50zu29^-8n݌D3͑7gyJdO3m-6 j=EG譿,%iQhro juVګ՞Ccθg 0eqԡ4a}xxl6d@_ ԆsG9N~USEIǻ/Lk?>$wH%SJԌw2g4p'' 0hjVXeK H *Żh>;ӆMƑ_J?ӓjV42̝STi>JBatNykYyNb(/:kՓ)[pމHy]0Y^Fા-{}&ɵlDq$_xO/۱,3bMo^\7,Yla mV~$r^*.z%ۍn˹5t s 쵎ه_Ca؟S2siO*sҨUŌjAXsgs^%{̾PD#V 7l=5!!>ԶBUJ8,yr~vv KLޘJVsA0  (]'{7 YܻzO\2xNK uq|vVq`."q13eQ7k}DӵlW= M 5tXQ[]#fڗvu]{%r*1 h^/ʗEHR=}VO#O}JVtoq$Ojů뗆':OU0v= (`oh}7d|aN =6ZAvÊp I87a ^DcZoD)_6ؿ7-I#f {oyNf4̓rrG_I.oĂ;_bykA;rx(|qț}>wd:*O'';V'ego^-y-eWFK`_ڰE[WpmfrW\ĸYNq ~%%!mlHE嘗̲ﭤpDpԶEobp[ѳwYMDS[V|eEd{[^s~L,I6Pgf I=wIxV ->f($TnY;&0?#^>&ҼD9}GJS93UeA1 1jyg'5]\oTY*M#{aA[DA:| 졣dSˬY"hxĕ s߰.X,)N85&x rq6)G3k_9PE?p};uNGWu~N7lSIwq5LBx~hsPH+LҏɇkO7?bFz*m/~V,KGѫYFhR+c nWg$At|jyXEGzL0>N endstream endobj 3218 0 obj << /Type /FontDescriptor /FontName /IZCVVU+CMSS8 /Flags 4 /FontBBox [-65 -250 1062 761] /Ascent 694 /CapHeight 694 /Descent -194 /ItalicAngle 0 /StemV 87 /XHeight 444 /CharSet (/d/e/f/four/one/plus/six/three/two) /FontFile 3217 0 R >> endobj 3219 0 obj << /Length1 2435 /Length2 14815 /Length3 0 /Length 16226 /Filter /FlateDecode >> stream xڍeTJH;&0NnN .9s ;뮗TQ^(ngLSQdf01201 RP5@G'-6"@#gLl*gg v09x9y,LL5sLr i;["#Mhܜtl #[bg:{O>4 ok 231^]v(?Io ,l@O3xKbM5,I9wERA@SE?N[lvNgb>0N~Sؙٚ,#GG#Dp ^WS`ds|fvu(`8"Q7083Q7b0JFF]7g~#p>x#pA7b0F|j8oΠ/~#0wli/bL /o:h@'mw\p5JX6`/G̿v.MC0sG?gmkу햞D8nr&뎐l"_#EԱB(덀y 7U}B%V8tH|GWmY,!-e!]wT[6AQd2;j6uGHuF"eQ_)@y-u=2<6Xh-pW`TnVDYx-KnD5:սn]z"++>&|jf.c4RKçy`IM+ r}? %A"]Q'M{` +!i+6PBQz͓ys[huߓ$Y,R:6x Vc\O܊2s'|u6ٻPM#hӕn|C(7lbpt0 8,17o52N ՠ8/iR)K+~ v ~#,NB98ñ‹ڬ:ƶ$<'~vMpٓ/C[9/>DwKeQ]c$KUڝqPTK9B} ?]UDpDk\!^T76W\CMAg4V!8e{^c9SR6.H9,2k.bxmTx@GlzB6dU3(ةAJIr`E!}O oɹ8V k(`$Zs,~Uea1G,5BM6$Wˉq3l2ev.A r\ejS:i2Q;|ݤ%3]1 Sn5?o{zLhb@⛶Wq,ߛcJx3tߍ䅯Ay.UnSg&;SDӝ^? ԓwL$T&~*/?k߳E=p"@F9r@a:fלc☖A!liIkICV3cҽ}0ss,RSl\.GfήLPq:~a*o=`_nM83Jye$~g,@2慔YxaҐ:{Ձ'WeO^p1v[ДcՑV>W%9E^Y( d \_ҥtgMl9ԎM!W-$[]ٚ:l* :L"N͖s&S@Ec;c3B -4Ou2q;+pHo)-/{Dý]&Ȓ.#Zǘ>TI*^QQ#@d9"zLꓯE1] lֱhJg.ڶi~Z.C#{8wdњ-"_XhS|"lNNKv:e;7(AwbޭCxq%vbBb oJ-҉Ac|>~ >Q\ԀI):Qw2ct=+ZHG"c~oco6d}$߮&uȻ<&QikhN$[Re}U(Q#tfj8,zq<=T[ ~U"1Ι=~많7djgB>D 1(ޝb֌GJ~I6JX"K#PC=-Y*!\ F9MsX\K?  +$G䒝l=d`bVCĦA'vȻJ;1?5N@dlBb*Cw_A4[Q9Wgۯ.`΀%6ל]w{hq祙faD3YUXC/J΢m;:|-P"ݨ5-sIQuvޅҋcCE_1rsłPn;:$# "'ܫ,~̻X5ƶ*b 0su< *~O oE-^L?GZ%uv}%Y㳳y z-! v_:Ly>$QԝUYZxiij~Q_GJMܑ\VF{ ]bvAD1]N i8onˡ$o="zeF@gǕ" &z_9v:2|뮽0,j&Swz=ub}]>М d(1`6Rmear$.grJ ]/⥡>"w)aDRB-?3V2'sF :.1s1'~G\%1F>-R՜r{i8Gtպ i'$5:GT `EyP^^%^9,PX{̀/rp% k1/*\뗰bžlw V@K|A T8)X;l!8OlVQ9g=8pӣwD,-.e1c`n1r]m෻MdahͧeGXLB/~ :vDGLN3?m˂Av*>&dAs z)YKJCp;zHxW7^53qd-ң ӗM1~^Okʼi~T6ev"T܈5yMIx(_Vyӄl4&2lUJ\E֛8Ǖr?q(t0E QVM8| 28%lUtdJOS$W=7QgΣVBDg !KS&Vf'-aÍ=oX1h˷}'QoxԼ 5T @6a8- 7U0 ͂Dt?9f;5GydtMyBƊγh`=xϴs/ I#ēy%ZҳOvGOCmQ5ppX.AG:Uwc8I ;0FHfFBCDŽ'؂([~hNG*19|m#xE H(ɀc-}gHF{p85Y`,=u偭jopdO@~9e͆/#K"iO$+Fn>KΌj%Wsj0N*e,r5%k :$<,0\1c2OD4_"ii "deMne,Q0Qt[\2$#,7`ӽ0DZi0.do-+yqzܵ$ԫY!q} &j9'+l'H a> jihaYr7 Je}^x+POI9¸z5!Q/$8zNn`z~˃х2^5p GXL$q́R{@iL>X<:dށX{7Rkx˗@#aƒ<ȐPϴֵB5jwFXp!2wFΔ[Կu/-88޺1uV(}D qG;A,7V #˄-s?[!}%=?%un;C1ܧyAK+7nn[[]ZLIXJJvq~ +BʫM,L-\#xo|, دh(wɈҒ}fNV(`.kJ_> &V@xu^ȡIĺߑmXy\Mz/V{,ɼkIG܆'LWk4K\|:[,aE K%NzG l,j.׋-ϜXgd]- WYgZ_q7.Dž#DsKF[ ZQ_wEmuf*#XV3_ķN*1Ԏ|hS;.:>#}:T]5rzuzz:kN'DkƮ#TC!lTV  hzS0WG;Iukua}ZSmE:0-M.j5~-ť-9e`M1gYOW43W 7 {a*)-Ppkc]ժ|afҚ} gw`!P|PoG|9x+Ӌ'z%KGdFFj;be'?*6ӳ,ڹ7Iy@eapuʖֵsSde_(=̑{ʽixK; Sh qCʋ;z#v^5=32mיo6{g(2'-Sؿ3kpY+=pܑd1`;) $:-1 bRI">NǣURBdk="x` С}˜r&-BUq.:pJG^)n veU WTKC\qm׬p[F hгLTy–]ZSckmRf-Y! fb$pp 4mBV0ɺ> ]&=0au-΃bOFR&է'2Sba&a*)sQI`syzodAE3aDon6`[;r܇Fz߼#,.at&mq*C8`oWw>Y\޻]q1oD\fkDWN*_hm\̑MƷSMޗE2Uv2]l;+RZ&624x֜ܨd%ZKc%T/4s ]#W/kh"@3Ahx8Dte5xk0z1G⻙фMcMdr<=,'8`Wbcݸpy:wmmQKq{yg-Sm]֠q[h}H]–h>k&f ALe,܇KݟB.DϳFL)j1N:YDڱf6Y}w+ 2I>VԆI6aٸ#D9NQkyQoGTjO{jT?lCYF*ʊ#[ ]F4֥_5PؓNB]}CnQS&T558)OA~yYi,v4)eY&}!e>V'^.K.;RZ6Q/w^Wr (!ͰB21d FmD˺ !#\}iV|h}p>ۙ`Cmֿ !,&]E1)ڙZY=K_0TR".0`4_͌[ӟlVHSJ&s'f 鋊06a2+q/muJFHɎ+|T]f@g,SA$/ͪ??=V.evEIV;YWw c9H-WpTqN'j*TSy~Tww0eOڦmw D$HH~J,c`f HڀYv^5I_kwe YGʥ,y(.7ZK:O&RPQv@\o[lf;-sF׃l'Y"zȭZ_bIZ1 7RKi~l @p_R(l5/k_S!nԅgŠG*'09-r#U%2o yE"/2+;!@/VOgo]|RRvNyvm-888G ? i1Ea,H'w"e; %+* Qʎ/@.Pe$vZ{.ޙ8sv{oHUǺ T^H i ܧQ>[5j|OOe@xv嚋G@!(n3N!GpX gܥ4`%χGnɇo-թٯSϻ72mŇjbbvجd'G.a<8uě=”0+WpVQF2Yr$ <]wG!_aW {F)]$׮#9'1xt4Ej Ne?"[~ WLi>aD=OgcdS$'d9/̨¡.6O 2e}jr/uRKiJvI?=,F^@mZQ}$`[εLx=6Nhrf,3}a(.#qtuʫ#Ot$gKWo> )BHo  H"]iu !ZckD;b !(`Y,VuL%\u[HyS49ln306 4h|PgF{R"SI_:iR~zB E<\r.5Գ*+)N^^w{s"44x$39^+WsqV?#`Y`D0>%xPԬ? aᴤLTh`k I5M~*=yxbsD/ry!'/2U+ZMpom|wn3WU ]Kbj:X RV*oJWf&C}˩Q?:lO 9p>a螗D3qgF$;" 発{l{=J'e6VD%EE RLEugAbL5f)s;eDc*J"RQuty|CxW:Wy7w3+ěC_fΞ6eҨ7jCA3/IK$T=o.c_j۾TFvWY-޾`0TWPٵ%髿hPMV|ܓQ_fE5V7{ 6_HΑ?]l)ƅ h^vR/֮DƉK/h~ؗ zҷ{w? b}zJY.9?mDα'$+ߛIʟrdB`a3~C4尩8%y?JA c1tM | g\L!Uw>-&qę ג W܆߬'n{!r;?y-.wjX^Pf?`ob#H~]#d$3.%:C[u{k V{i.cQE|rm?J\}ӈxxZ^)Ã냋sfEi&8_}(:kO%x̝C襀9~ᄾw}28"8s|9wKL!sD6z4Eo = o8{5]j(K]1,QaLEzSb`R\|O uu>8u~(N>~c\Bx1w[>FA(q/A5A)0Dfpxb{%4ꕨ2&>!O'VՑ~ %z6oQ/Yo:@J(iThtծgqP"{?c X7uW Dp".z|HrX=1nKjJ(s$sߚ+/O%OjY /}\ہFhLj%ڡ"{lU!3Ym06Ƶ 3qFf4ix2? ·ߒ9tm!U7yh}iV-"5Wy~E= zE]cA9lU ل4ma1\Lk(x_'nHVzATl72~Mʓ : YG=9Km y[2oHRq{ м(Q }WPs?}L#1vPHC)"/V'&oyJ_̔"Ru({]3p[=^;H::c7s%RZAQp[un2p{ùAEN6QG/[;u ̗İ٫|2y?(oUHsX( 94`@vaR B%}^%q_k\W3ٺ\/Oh[&5z"G\gݔazF(6-j:4u8?!g#M\(B'|F%ի~_!u~`|T[C&RQz*v Q"CY]|1HVZ#Ӽ'^:\KBr Eݽ5"E Sc-1K VxӸ+ݎу/0"~!P_>02EqM RRg > Nia]Fz!?-Λﮚal!'}ݤc\C_`BﭐQ5Ya|_6/q@5TsQ\,wէ(ݜ62ޥF&F6Ԥk K3B ~-TBCǽD}o <_3ߢhpqںL  = Rwuhlj4עuW.RaE` 5T fȜh[ȅp62uI^;ST.a|%_ARJ킐i*} f)Q(q?V9ZU"]^L[0&؟@39g]\̯,žeV9?S\@ %- m[[g8hXNsB%ٌg}.6geR.W>X9aGla6"Ub/S|sqvI(wQ6e.1ZiYs25tXQ͝23Ҙ/mA/qZب9fg=<%.u1]i"&:9? QHWO,[()IǾLI#Zf[HD Q3N\Z"iݱL+?:bSX-sL`CZ 1Όl"<sBV+_EtAABM!ŖVT$Sk -svgCe62d(vW;ϡ6ЦQMK)gP-;9JY,Lz¶atARnIOJ"eT[kލފT!ů_t2gw'n§7/ivk=p ,e"ȟƛjĠ'd8DJ 3>HZRU i*C.ۗW2{l5Ur6ZwGmN }s_hg~ NOYP2sMCѹOU1%n)fMuT,n4J'd-(&̓K}9Xf{Z(1륃=n{"7גv`FQU^<ή #\yt0sqRWtX!i`Q'&F#*"1~}\I2>J>?(3qYN[4JG\덏bcc]Ʃh\*_3q޴Zy Z:.D: pd~ qD8W-hUa$Y+%,|^uσ7H龡4||D>2U,+QoY <[ rsaǚ1xEMbu 0lrh]g|2̵XgWH1K*!\LL<uqj9$#盕_LEtnJd1P:O[8NHzw0~"QƠ c /wkyk>~`TeU }Y۝U('(6Z( ^a7fݽ:觳$)+vL8HpV{R/kR?܋~mQ5~=` Ue(,jEv2` sUEf˕X>-r\w6,/Yia˒ThL)jgDMYMTȚcr2fBM$FW֍Scd)-,ǔ+|C*ܓ= [' <j>}%AtTfiU,} h?%u 6Uɟ芈`:LV~ZA9LmDcUdn%˗yEFGgΗ^2n8S: !& LYo{nA9b؉ڮW$vYj’'݇{#,s Oel0N+MDt@BԛW$c$dÛz6$Pb6H.#@&]kĸzϢ$@v4̰0)yHeC̤}Z:s &bQ;#{JoK 5fH ihx߁_;ou:̻&/!x|`+mzh3,?gɯkƐ8zfÓizި4m(&/A-9n8=輤RܸZr ri-GvO|OƗ.][funbAg!hʌfuoopsdO~,zI-J>*A?2kTRX >AGQ6`xaɺQzB˥[HmER=T2FAB@NN3{{ﰢhDzMR 7lxˊbD/]BD͈/?"P@a3]ay8;h,vH* ] ܨ$;)mOҀ+-d1Ic>ds6N2퓋X4Җ] W.vQϼDdOf 9 WO?se$n_VhREGyZG"SXq(;US6\;wZbAԣ*{^ f1;f /'{'Zj|J|!/X̠T6g pKCeHmoh˪G[tqJuNO,3cY!|/Rn[0joZ6C䦜~qcNQΧ{ۂS#.}%4)>_mװRuq;tW%qmf#DT6ӹ> endobj 3221 0 obj << /Length1 2049 /Length2 10596 /Length3 0 /Length 11826 /Filter /FlateDecode >> stream xڍT ݍ, Ұtww4 ,t7HHIHHHt Hww7*]wkfk{JMEb8ʚ@ rjA9hu@.`I&ee*C vN;;%B\Rf`K2+@rE8ymܠ@o`e+ r[9l@ЊfM?)lܜ<==Y\Y!." O @ rY~9ƊF вфXyP= qwJU'd ̀`ge/?ѿ 6889zV`{@UFˍ`hhf ƛy̡nWA%# %Wh-%! G7W_,f~!A+/!Nlڎ`gw?$ |(3ea/'/3T `[?|]<@7wEhKd vDjY#7#YBe6=eM-5畐x|Yy,@;D_YV*W?A0 : xZ@^B,+$nol:nQ@RuA2nfEw; ;F dv{ h{#H @C.yq_.trp\\̼ѠE_vZq#  XA\~+7Mo`xlM? F6߈&A(>AǗ73l!..(>ٿzfdZp++zL? 4wuhllOoBZP1!tH}< @~׆ro=;zNMn T pk5r2Bs?GSء]P@h ߐ*=_G:>n@ / B0̶:R̓e{D4Ze1[zfVb|mu߭ZoKJ=kJ󸙧KةD߫3؍0yE.0j8ֽ~ts/ ex^uTg*=9pk2IBUTJ:P Zg%`n҂ϥ+t>`yZɾ/j-ubXōeɻY_)xw9C9P6FoeB#MQ/H| |y:@ Wbij&vo\x[HBa!ѿɎY {fdc1\Q1wJMuN(&Oͫ׺ |4:ZtaߧSQ\[l"@b1;}~>ΓyhHͅTu)f.&r@{_: zD7e #d̢qĥ'GF!Ugyks./扚1(FsH}BMtr.\HB+51N kjhZ=GMvݏ1]. {$MuM4 3G`1wx}:-uЈ?&^УSK Ǻ+eW?N#n ay 8[i8$`@ȣzIJ`j}xi) }nȲ|0)NnH~('P_Zk}cJ Z)KwuсԵy?Š/$ Ad&Չۙ/6+&^)Qqι 9v(D6W5N~LY%& "`0hzZ|1wUI³*&Ҏ5i2r'rZ"uO8]/1f*ܶDŤXFRA'QX.[d5fƯzReEC:w%Tl6n X o<=3ӭ\jL5CPO _ v-L0ԁnĕ##“Pl.`Qld3Dv6ɚy6F ?r(-{!]b|dـ~q@>-]p,fe u1xܲ &eG5WD5![ŏWQ4x٘Bڕ_j^ϵzpCM|d{u_?lmt!.e~8?t i:Wυ//w#xkfw}۹,78A_atαlڳ;ᣈ-qvԞb_onqqyMEw .G VKlduN &n?\6H6"LV&<$|qt>r&wէ 9FgH&k/zgĊ<8AӋ9u?~Bz P+# nL<*}ܮ4Q]c6O_]-j8ԮLt`]LZGc򾎈~ޕ `~[ҿV'LP}ڜ'4+L_L{Yĥ(a\$OQd򻛗 6V6j8.l0rE OCP㒚[L}SmZSI M2ߴLN&uD==9ӵ3ㅓIMer`Ƒ5-I";m/SQTħz}EHB?kȫ7Pk´NAn6TV(&|fz({Uc2Π]piuKh[bŝ#U8k/0 =]I:ܻh8?2 |"ҥ'F_ٖWyH^,3^7uwi65؂7Hޥ[fk=Mvk1q`;N\S6T+1ƗR`>. 36"ʄy·15.b-Ly9ro<\I4i]pFf{sz)NZaC×Ik? ӊ??쪻H(&= وs&S=F&-@hR)r,G{P[G h5=@*,+F8[0I%N& "|Yϡm8$.&]Q-m5'ƹ6&:o.mݟAkx/)6Dt.9ZREVpX'Ǡ޸c $JeٮWl ;+. ݮx56Εk;7v <2&ZKuI%UπD[~~p׊`7EK$|`SJ1w #(qT#L=TNvY¬6MKiLUKvIҞ~q״O Z j\ZC$a U? 3KڭR4,?ߝ&/=Bp 3-f@ً6Hy23yI?y*5WS(sQ__6J͏Gc$@D"SfS᥆u(t#XTN%|ZS[ %#JC[ V'9ΈA 9MX qTvp*O/9XBɕCnLRiJpOM{P"EbK\ǵtioSWdlҘ癩\W+.W Iu &*~)9aE2?Ò.h(.^Nw/D"t>HhrywH!q[U10hKj'Qn ƥS&4汫@rss˸T8LEFTBùV #0{Dy}6g=MۛDqEF[[NMOo֗*mKG/ף=G)]t|M144~vR_A(Lӈ u }B>C3Z~=הSVϯ<޾U'/d=faՅJAvMzBV!S8}7OzBC(.25bƓ6Yx,-E5ցR ւjo$l{ bf$5:0B{Dn#`b݃g dfi,g,:=$!Bqf哟L^!Blߞ߶DЪ"Hr *|_i`TH ?=3`{;؏`7Zn}nz)-I|ـkAΟoj/ :dfvF&\jR8.W&GXt$p|d5mf1 vP+I;Wn}~t'`&]@RGՎ HވuSz)u Vh׷T2Cy!jk$-*Q1rzޯIYFI[47YyQˎd球$-DbnyT:cshҎnlLTAOO0K=ڜ˻EF=Cw =07br6Ӿv;j;~A]Q# \zi-m%Km UZ:C[uP*~{"ES~)يki?rY~~_buoCJJ :b.+\W{\F  V8;uIk,«,)̬VƉx&7Pr"]+l%K*zTmд07Inp9~7='LL%:PFC1Zgz89dɍ\ZB-0t&A_:t~TvI&Lz@dP¹lll-WOHxx7Q+_OO)7 b41r*l>*4r SGAѨԣly8]1a W_ŴxU]T<,]L/֑;vf܋\RY"1~澡7;GK$+c2TOhz|SVD1aײl)b6|[{"YTM/w3q>1Z`y.8*6~4с@tuHJLO~Yx$Y\^/b O S<4d{b+&BlNO%oioR'^\?Dy1ն%l%n/RHTUYJfOϒA% lO9~5\dR Y{' GC˾у$~7 볿>e݄y!REb=ѵbHzM9ɩT$\K¡L584d싛ޓOuEF%Ct{I,&e<%ϓM_ ` #XpxRћMg̯BQeDBs%p] /(D / *nET2٫h/ 1{|qgGɛ(ODpo[D[kBji0|^ة؝2k͔ PଣLi}Y?lb#:lrN/$ޡY$!7)ťP9HІQa0YMzng5b.N&g}7"w?M_: P( 6RI019*:W7x&OW ixk@dͫX] \3*  I|=r=zSa9 .s9!_]$ Ê< ?!aϴ?mp|$lng۳͇ω7[\ZOoמƪFߋ%^enr#-#ՄjWfOge!n0WJ1\#OT}x"}i ;ۭ$، $'&6>7O9a'5V:?C(߉hs•-Wj=蒿7EH4yxRE^xȥ${Ă).U\3&;y*DVZzN|ob*Ȥ`fzFHɡ3Y~EL jikhW:=Q4>F=rfõ N{|g+ q>5RJ^$$Kl;990GpiI'Wx/:YG[0v_ۧ'N۹>7U%*y` Fr,ͬ\\M a=6fzcw($sC6.7s2h6*]`fրIMAF{ٸY fMfr.֐io:lSaG8)X- Z^,J7 >o4)RLb J_¼])x$uuqF8.=r8~ȊzjcrFlSs Yc/3:mgg8fd+cjP"85EdpZ[ADۭO;t]!\6e?T%27X_Biz,c!ƙR91`VdVB>g yv^(a\w̿ŵ#Y$UOmPزA$GV=X< 鋂 kгۍN]]*oH??'>> iC~ /7jCv+(,봉)l>Df5GZ$Xs]GӤ )N ^\eŤ &b mFjڏׄ$qN+m=$NYqMYpaKlz>k˔|z xp-//g%ʧef5Cgqh"zUUh~Vŷa-Jcgv24wrdz.*d>-]U\ 4wgy!`s? Uo oLDSjq,wf+yc[ m'vMU>{7Ss׽.#/ܲ^ Bȳ9~?"`g73&4ETX {4 ac=7\&ls-xi!x}rBqD2 T $~k:(0/8 e[gFV1Ti{㮕 ۰[^Ež~2q\`ĠB5q%wZY`.W9Ý[>M 8>dS#`kL{]rB -P^A JئtCÂO-*Ӽ%ۜO?;_ |~Wz"dd'=*(މKT*OЪMk/!GW `=Zդn$QR[RND-ڄaC=\̇g*3j`ҚE@*bh3onB[)[=Kе% (2YYU,p=OHgcDI2-RCfNXa .?P2ⲗ?F^|+ f4q\}vi#b8 v,^x(Y/",ոrQӭ O`-uNYI71VF?7b4aSk*,F?TvdZnWLH=FwɢvKz_;^pNr#?BDf#VJQ(l|h&(*/y&0%C*w<" ܪYh-`U7'˷GYD؈P *];@ moa2 ! *=HI$_^?؋+nژѕ5l(34|δ=Q!:ֆCa#Nėy}KW)5t.{2JzR!&$fW> Ek4$/'EYk(y 9 hYS;*syh3D}.f};A_}XO߿E~r9(24XP@jd]_`C xJn5NǾZBfXZ>/ ơz܏ō3ˎʆ <a)ky%c?R6P#W98m LK뒤9n>%-j8bY(owYl1Sݸl/K-m&r{"VZ&g'QjN}~M+sSH rsf8{`MAP* MJfte+,$IC N LI{!k=76u痑 Sl~{{a3|x?Uزǧ+(1ϕzz;+r8y"'|q?EN:kľʥ Zś~J/%$ puyJv {屒V;,MiF#Ee:=rΧT][y"Ź.5`?L/)_Vzql$BqPPql,OzUgKlv?, $ca $ Z z@ } T2ϷG-$C,X@z CZM ƶcهb; ݟYZ*jeq[^7]Px0u~I{}f\adb<}Ӈi %\۫a;*bOȱ9gd {w,9YO|U#ދM dM^ R BC'3\ nfj=FC/c옥0=sV/GI^{GԦhK>#UwĠ Qz"*)| i?8q endstream endobj 3222 0 obj << /Type /FontDescriptor /FontName /NNXMST+CMSSI10 /Flags 4 /FontBBox [-97 -250 1077 759] /Ascent 694 /CapHeight 694 /Descent -194 /ItalicAngle -12 /StemV 80 /XHeight 444 /CharSet (/A/B/C/D/F/H/I/M/S/W/a/b/c/comma/d/e/f/ffi/four/g/h/hyphen/i/k/l/m/n/o/p/parenleft/parenright/period/question/quoteright/r/s/t/u/v/w/x/y) /FontFile 3221 0 R >> endobj 3223 0 obj << /Length1 1419 /Length2 6027 /Length3 0 /Length 6983 /Filter /FlateDecode >> stream xڍTTSkEDz4CMA@HD $H& "IQ&HQ "HW}oV:93g>L-6(5,,$@DRR XȿH,A+7 }0<iA}=@  Y@1X&1h$Z@E㉍Ap!t@#Ey-0p+x/‰cnB@h!~H'i1 8+bqðH ቂ#8b/z@o$/_QJK]wB(dQh7+ 46E04'a~0'̅uvP[ #RMǢ8q'I2{B#40^^H4G|(,N@z1hߦ+ pI B||zAD?>7$( @$$H 22+MdLx]D(W$񏚀!x/2(8tCNt#]+E! B~~F\2ה"8UW br@1P" J]+C}#NWIֿjOBe0,H !TZH  @8',ϹJ@!@pOoSe %j:%|$2 #DگR[pfU؇|GJ|ր|ţ R6 mM>Y3ۄŧ<vxWx\J"xGjIrlR/*aIL06S -n\y3/R-qcsUq!+@z}_i$~WB8W+:;ڸ[/}3i)v4(*re'0kZ:=HIURa˼]\'HKKҡ1+?y=*K^$%҂\Fd.z@*K?oP.@_x1TטMFc4I~|$ڊRy)~8R]<8 W*6]7 d T*4**#OXҽK0YqϹD}מS#$f)&h* s,\8-˥΋oI)Ŝ3=;f~Uئ+-R%szpy \ ,D{CNQ3԰0WqX0ᮂǹ6PZ_ѭ}J.Eݻ ; p\XuR@*Xe^5fp>Zԇ~[}jhLbI߸gVu#`3趽вu;<w0R,+Krxll`iȪ ZVG`W{THnev=x2w7 A_T,2G% Nl.##[bstFYLd` cՐdOY+jR]O`K%bQ})e'!u*_'kR,N4U5Wd d[1ى-pt򌖩t&QNn {s8k"Wd.gRI)B|ybNcuGj2t]v[ P%$ ?-!T׆ԗ"s{SSX1ګswˌ]zù__LdޣW?Bnt6?",Thz͒` mX '?jRY2s@;"lt~d|ğ)4v#'jV$[ZX 1.,rW \VYFe+2ZӯIǧj谓hy 帄7T:bc|ELZB|krg6-I_Rڨ_>Gy+Kz7K+L۠#& +mp9 ל"B%>2*sႰMH~|0lq`_yPQJM`6<^P pߩL-0[ڎuy]?;qʌr0Wkr*(\HTTW!{]ҾJ KhWEK#RKTނ ,^?6)IQ u熆s EdZ7ҹ]qcHhocʛBv!./f*<֯;4CU&˜۝?;({~u GuY@$YEu.MrbdJE~yf{Spw1|1mĸQRhEhIdĽUWʄ !gψ׆ׇo"T[v>c]ΎZӥ} EnD)(`OrCzzlUjp\:[G|!5r~#>Xs%\%%&|Ǝ~cOG Lk-'JL|k[$ |36Ë\p}\]4w/.I><+6ɩ-iY^agmm$c/g6l,'wχ @$ĄZÆj]kS[CqWl|cϴ3A.NFT{2o&PK 1;1ᠡ' X1|o805Hr9t|grpk{'-eϞwB͐zW-п}XiaȘ>֬OdIW&;m!']G>qppЗcȣu؝mQ,Fؖƽ7mgO g96v/1S7;߹j~1JՏƘ|sB 6VMx?ApnHg;/))ɻ"у'W? 8^Â\4֭-DX4WP R*2PU1y> UZ~l%VurlP *c]4;2~FT3A:[{a\ġ+Qu_Q~w!pNhR3Te kޣ?utaΎBO15x=esRV+4EMD/.% '<w[~aOHޏN}k lȕG2 2v[uZ Kb??ܐg6Bxgў+^.dG'<0*Hz$*^C1j+#pŐ6LޭgQm&/ۜTBE&-qRS]_192^<Դs Om\oµS6+$k)='kOdX3)aw1.` tG)r}9Yn_ca&#n b~XQa)UZkHÒ{)p7YN=@kMfOQV;x͝M >/ed Vk,g?>mDƟS'jwY 3ñldᇃ׷n#n (/ M*J \jyZ?O̟3 w{唻GDwa2YFcBʃu{@9zV4m-E߲e6"Hi'hԶ7@kp^n+ nÂ;gSck_ӫw\?h7}o[ $ i~+`=zQWCPucnEz2oܖU*/Mw=|ٯT9Z=-RWEk<-9yȯpGcZWj XԂ ޱ{t6c`P|(MYk_őR2<3 JL/"IuRTKS-J5sd~:^&uH2sHv\y2x_" Lxw^akeac$ oA`1?5y ׌V)s @^l԰tgM8(U:&(]'Ch !⑉;gIk|aԒ”mUw@ܤԚfU%W6N!LC1:Iv)MF;mi a!ٞy.J;U㐕X/o]3mOΜ{tߧ_S+<2au,,27nZ=է2rlvsB]{E3F1XM`}qBV%Ȅ8&KoPvep^/U8~]z@X1Z@AJPGSkhϐMtD#/7v9%0"k}|kX'Bै?dm_,Uc¥&'4IVlcǪ3ѓ&q3MW8+>Im|w^oap]~ym|=+u?_Rm\(@SӦZb)"^2/,?Bvk o)PBhAGr/.nuB[ӟIt5A|V[5켕 K)-ݏ_;j Uu ` GKrC덄nKҭ2E,jc|WL(εϥ-1'p~&.EfW!9Pͽ:0@+PeQcE{p{Z= lUFkÈec-KлARcfV6jOG4)iǤ *SOr؅c:v˅$sgPa{ Nx`zx2"h.,+\>:jI9zFZ}zn8uD: %Kaa!iW̴uQ R9*,yjL҂"Ȅ8GvbNy } c9 ao Ld>ͼ \&o?`Ƴ=-%?`o {4aH)ߋ-9+!MG>Ž>Ʃ|%ݽn]"3ԙ6[Bzl8@Zx`RPN>i}w+=s7ZW ! ߽n΀ c/<狐f N\[;j=w3&ݓ믭K'e 9ԪSXK/\8ޛ#Yiep<^V*o-Yz􈥏"`:oK_mFbڷ=Xwﴯ\;lۤE%:bzILTy%fh>]ϺwlGX_:Xσ>v,ee0_+HW?'_WT5 MZ>YwՔLgp /{xu]ʣVm&P<ų6qC󆃺Qbȇ$qOq+{yħOD7vd|uWyBh*BuֈdZ-C>edTwZ,+UPC}24tx՝(+=iѪa*LqW+)z)稪dxONXΉ~CkL(4۵wgc endstream endobj 3224 0 obj << /Type /FontDescriptor /FontName /DJLTJK+CMSSI12 /Flags 4 /FontBBox [-98 -251 1052 758] /Ascent 694 /CapHeight 694 /Descent -194 /ItalicAngle -12 /StemV 78 /XHeight 444 /CharSet (/x/y) /FontFile 3223 0 R >> endobj 3225 0 obj << /Length1 1427 /Length2 6409 /Length3 0 /Length 7371 /Filter /FlateDecode >> stream xڍtTS6J'4*^{! J!tP^WIiA""HiTs=v<3>< h{:e]ccMi EIMXW~n3FBbq>U(E-/W"@$e!R`0  DcdU7 Zh“[A::aq}~xa|DFFJw: aP :!paPW C"~({ uy 1|!<oEЃ!P&LX(HKB0:?@!*'W!$w2CCQ~H#tE:X_ Eh\>tԕ (~0 )tQW5*h77 I|H w??uA}P[H ) THsD` 0, $򫁉;wˍvp4AH$/DPi@  G$qn_6n/` fSr7E-TuPWPY Ap % Y_W7^(.r@2]LH젇 [V` 0 wO{P7N^Xrq+o9⯍E^nBqKr ]"驎E X_J{H~O1\p_Oܼ~gS5 Ə$nSDQh,. _S%/_& D `pk[#m &\zR#2tʷ;BC6D>jO8w){M,`?bS_wd4qqti,): /eh&sRd)JZy|!)ƺaxejMM{ṭ; R@J6@Zf] SxH5r1%Wvu2Iԝ}6L%y2y^QS"Z Ʒ5[\xqmΫ^ټ\]!ۖ۝O{(\MKs ۦoHD4LJ_d.b+R50kTpQG;ZkRb=C,V^+bos_n< T5:tk/IXT27,1i6=.U,Rʷ3 e@l*Z6@Bo%+#|Fn.vWC]_vQ(U[́m4A9ݴ}K@wbJ9Z*s>+WGX/w~ ;Vgfꎘ9 r$.q;x:5Z ǯn\V;!XV0De&owUgґV+Jbp{~piG٦3O^~#|Z"x>6r {:lMK[?u۬-AK;tnLʍq7L_R{01ǴcA ;yz2CI uɅҨm玫 LH$#޵)M4Y pX'?<Dž21ND|^@^Zׇ12LJ m+3GLBrfĥS`;h{v2o졕3IZburjo)i5]K F88Jgw~7_ W0yGNy&iǑ=_{HPtGVV,PbjÝIн|D>W r1SG9s&&. gw=‹Ƣ_$ܖZOR\#e;^ Ij'a7x;AevZIBGn8حn#&Yo &Q}Yjv;3QdKkmMꈴQ~?|S|~?k).m;trT@`}dyU`z(B@Og]wPkROjkE邤1DϓQ܆ޮVK="5W8̫ 8;8Q-ظjx6]]Ǟt?ne<9APPzz:_HS$n?Q-,3^@y*}\!>vBܙ=8)"mNzpԐI▲$Ilv3E*Qhp![vLÅGC^r Z @K`7K8uݩoCQC(̧<{&|}nFܶdӄJ"WAKk}Öގ~ƋdoZ Tx:ړ={uaHھջz_&0FpU|B>0DRXYk,dߌf RP[d]9WF%q*c0:Dnnc%Bj뉇=2ǫ'4`eN^Kr!aipbsB17w ~7 ^tD$yqKgg&^kO5WD _Gu^r䦊 w&[ƶ\[9h?=,剨`D{MMBٗ~Fӝ*[seuW=J{I |y˧rq`P׮ͳu<{jO*smJ Z_O̝8noxwoEf|z`G'!pF"p՘w@S+!0j986괨0ITQݘK̇'|wj7?#sV3`Ғ>"]Ol=,Y+ lLiT]p~|]qFt W#Y ǯ?[c4`jʹt"+:JMcö!_H N?VoT'z *?#lݧ \ĥ0dPB/:OԠ{?G7A.;E55습1d S>I7-blԤgdͫ_ W[t숂r'7>Wq)/*&$@E5SӾ`v4*PBњ} O0'h]kk5;O#Ruj״ΰxar_Sco"r0߀&TUbO!\֐08֣H{o;1^(|*.˫6[2K ,V\e律@5ly="YKF۰n]qK˿gmK<Ô̊#9k]pށ R|ֲj֕ H@|yu/wf[kYLԹ.}R6@݊VmeѪO=.U{vq7\8ka<|F1L^c'ZĄrOlhŚi{8s=;k42΍qcltq% t_97nz4zw|rvFrnH|O^֜ߝv]>u^?Xgz ?C"P /څ# CEF|#f5@LfS6Cy٠sNǰIAns1OC kKm%Z ļx6|O 6 t9N:o2oX'mjuZ ="8}zUvE*&Ύv9|=/Vvۭ ݍ>w; (*]_)aDC kz"GԢAHJ؇Q,ŏ&.巴O$ hJe? [ߦ4 ^ҧI.D=~ɉLX̻:ٮǷd Fwl7񚊪,h3bZ$|}+l#T팆x ]E΄a{NdH>_~YlF V{P&d1)ܦޒZ/D4B0\ >7Uܻ^_qH?L ?롙EJR%G%ys*^)>{ch]wDkK͏/ZIl/@{VWG{]N _T!GjƎS=@ ql;8,Ѣ?M\Zٿmqc9ȥJ@z_tgl%j]۱΢(Y{A2BKOosF?NJ <؍C܎;ݼ'N2kMb9 GV5_<_9GLSA WR Ia:f=߳ne dS.9HkI/p;hnixH&\>J(F^Q |4Z>4Talg_ӥ֒uRP~7$7'sG%H|K\ӱ9^ԗϙ%gkn"}F[(ϿUG;^dX9rMV J#P#U>gue]m}lVe^V;Xas8k+[rكT%T% h"oTP} cEʛ-תXZ>U3| E9#ox[P&"ZDϘW~,KEuc-=he fv{M+-*S Qܒ(~/ݼ^^K+а{¢́qai7 ߊJ 5ڦ@LgXNt9l[z:gBd:Tywv[ |M&Ή?(Dj[Dan:#PΥ=FlCj,E*R'ܻZ[]j8􊮌|iZVI;>f_> eM?qryp',o,lǷ9 ,u ?XCQ1nvpO w[?(Jl&T,@RִS4t.2=@9\v`v'EO:PlLP$ު; ѱiDQ3ru0O>N'ZPlb\ mk3EY2ǂ-42B(5\&Iab*9{W\cg}\@RsijL)FΑyꬤv\BfT)FK@pAS\̘*m|ہBդ?$)*=waI/?b˷N 3qnƊXF& pUIhn0q'~&J:yګTm !_4h$UWe .5ÑcZq,TÔS#˾Ein4QeEua[zirr.̋Vզ6%Z0H* /c/y*{WK^?HgWlˆk3+e8 &F# 5}&MG)%žsŬ2P~o $A^e;m\Q cX}T8Qתּz!7US]7|Υ{bs=;[1*1҃˖L$ >FUj?\s2F$0vs=7z Ǜᕮ}\m]ed<ӪpZ҃c' IjhANuk4ۓiܥ3cw27O=faj'VYM ʮSi95 endstream endobj 3226 0 obj << /Type /FontDescriptor /FontName /RSYDMR+CMSSI8 /Flags 4 /FontBBox [-100 -250 1135 761] /Ascent 694 /CapHeight 694 /Descent -194 /ItalicAngle -12 /StemV 89 /XHeight 444 /CharSet (/i/n/p) /FontFile 3225 0 R >> endobj 3227 0 obj << /Length1 1675 /Length2 7609 /Length3 0 /Length 8714 /Filter /FlateDecode >> stream xڍT[6NI4H3 3 C3 !JtKKHHHH |Z߷fy}{5L:rvp2 YY P8>CF0E0EԄ< $,@D8@d< |V#G-'$&&[sx8قaM0⊊h N\pH:"n|`WAtA/W-+Oj|G'_}=-@IHf"(= ۠( 䇰prC"N_9r:f%C"Ob:w_?ua`vҰt79{BpP?  w֑W_7ooC `JdA}#^߆A -`qpCZ0zavp+*rI?FyyW@ +& @ a ~sg;yTb%:ƆZpT?CPhz?o_mݑ'c:A}0PD͆&5!ChMZՐ`ԌP} z|Pv8!m꥿uAt_J 5z.*o5YA!a싏JBͪw`p$J@{*{C!_P?_E6`Pr-_rP?z A=AQ "( P}7:[8P0~7Ԯv UjT ǂڇ Ax EYzzxTU׿>b0p~qQ+Gͻ{u+6t F᩿N{wv/Fu+h.},z BWThJG?Nz vp T]zXsב"ۯ>?Bl\egLYD®=xS&5䈩qy FSҹ|G ܑق%}5/Ȩ1 QSY.lOltR4Y*]97%-֑6El$FZԇEZ՜Wj`,6% Z}x ̔}z&/ep7^Ѱaj19y>lڄ1vc7r@O>4Ť3o7YMlĈKIYm͙\<WTޥ"a&+6?ɜl$HTl@@c-G T{ɫkLo}DFAGi. Myx)dΗb*:SNZQuR&C.t0sԆU\8l}RCWCD3(Փstw.B!B]wez+YK[:;{8gt.RV*>ByuJ+?`rc/2a=lߙY}`ifK:9$f&o6#Z""zS׭8 CN0^,L֯Qv3K$d^{Z  K,xr 6p_&Mt0GNWYc -⎧s"D6?WӪ C;tdErT@k2lsPx72tGfcY Mq$NՎ.2V/gu;I=o>(7gs!%IlTMuQHwLEXXηSQaf ,z3eN-a*~99ܙ`~ԎEV7-ok[4~뷤nڄ \G#k̮iK4E'ޜ.$ڎ4N0^kδ<=i*^a7s]{iQ>:>Xc^z  -iDY%Rb9r Gixdq}y/.K}8zV@ 뛯h D__+RnQ(}BHz򼈡?C6ifg{HkUH^ԂB/mf@p -ArS$dplrl~[Sx S5&[(ޗRagz8e (ˬ:Xߴ^,"5Va!/я5Ҿ[SeˉZ ܘk-r=HhWݸM9Ab\>R')R\f_օMp HvbN; c m3q&%;.u5K k4rF^>0Bzz8-]NAJ0?2-u 'N9k?[,acbV-\c~F\ƇǃT;AZ>TQP S0I?8d4\ņ~_&&p) =ȶoP%Sρi2 ms Uw/Ǣ޺ˉn\ +20'{uFAoo/\C,Yɿ1=Ni~DLl a!gI+oJ @E%.cq%0*Wk{Jc/~T^Λ<)DaM?0O>\LX[2WuCiqsb\5_MĿwmKus[ѠxH'NshFqN.ʥ9ժs톚b,5-/r&td,i>;ZBF{Sq:nPgztwyb7ҹBxjyzHDf4f}Wnd! 0!4݄:!O!sn uYGru)t3)Q8K[w{ߩ&pD>wg3\E5Z뉣Q"7+SqL^S8(>CyyrOuWO}UXnh#Jw'[e4W8ѥ.7ö./5Le=}tF*>lmoX=6م<{-}ZljمϤM޺fBȎC) o)\<q?zG@8gslPxM"fy_(Ii&,;7y*~(Vhꚭy8@ru|yy~-Bw-ː& _vׯ\/bnL]7˴UHb T{l@ ;4~T'"uiG~ƔCyAk'kK|=# $Vu^zN=Ji#}ޡ k$|,Fkێ4Ȃ3?ˇ{5XG-ŗ5 XYǣ'WOβ5Ou?b٬UP𻝠7<3HwRŲ9+G #ӝ-qUOg󓐜.u=0wl+x$vMp9Ǖp,?m\[/}QuѿCȆXi=ߖ~1zhZtVK}rZS؇];YA[NbK*,YY4V.@U>/ vr {uRׂȝoIhcl#}u67Ng? HJ8f9Z/Kjj7Gsbk9WXBk0C{xR":&j/t y,6ϮSnxܮ>]޴ "B&~@,gI\UWOLUm@C-CzVSyԄ{>|Lp쵶}d_9"(!9R19cJ$qu;ix&d|:kj2ELc|w_1 -7_IM{&&.#D)+Uŵjdu9@+QW eo(˼>A8=/ /IgA"0dPqƪy[MD&P`"0>cfTxƱbTAz,a [M\y -wR7 PY TԤUGzp-.Ӌ̘O7$tPp5/T-"b|RZRى1jRWҰ%Q  q4AZoYSHvL; 1n%#Ml\Q'wH(7ň6: w#;˔ԯDDYN5C$~9!]>IAҩnven.ឰvLUA"kml39,oVQniCB e{w63uĴ+9ƻҾ[m+ 9u.k+|.QJm笚ja+_!罰ãf-hZm65)FB.j[bYɋSAdtSm[sUTY_syӃ9asi8"$SRzy 8ihm辦9=Շ9RipшWBփX,ȋ"7)vqx6 FI48yC}z.pA`Ezm:3QqpSl[Nm3MٮW?O%ݕ!0m8x{#'Q[U/]g F5h'}'u:[_Px> *H×o⽫?;D3j-N:h?Xintoiʷu7v*td<>B O\-(f7sZL\K,gVJ ҒVt1`~VQuMN ͜\!E}{Ю|\ 1.V%b?r^3tR f+Rp[)u㐿%Ovq!gjՌR2tw'8RѡgCyh1=)zF~8:h#W'&f40@D\J-,mUU143.VU(QMS0s^"94:]2!dKo$XZtya̬tLX99n/#r,łx2E.aE.3쓝-I=`k~5L+BGo'l䢹aXOo_/Z &pn(e۹)Kkh̞2cgOʶO?lƱQi6^ljgkLK tE_1:\8'<~˅W?-(\LSAAά3NsYtp޿_+Χw'H1HDj '}P fs:Gt-Hp* (wk&W' ?2A8*5u`"w4 xOI6D^FљTQ/f`6b"#*cLt)}O0Gœ§Ƀ!&)SWk,7{K@ ;ckeel靯:v^5ݺqz =T LmS*vq_sfqzP6Ѻ㢺rrrwEUQKWk XX<- aA#vI`*tj={eHuQyjc{. CeUI&G7 ]e}k(zTtfs3?0|"S=KIn~!yF(郳YD]j6 `}$-4} |F_pog-Cxٙ!AZ>2M -qJEG %Jֹw\uk徚 o+7sh4ϸL9_$#Zm+Jْɽ: T*Їr0i 4ib{yx{IKa%4A)&w Ղm6Vc! ziei!hp?S=E&*Jz{ԓ,8=esl!k$z߄KxXfUCLo]v?ف\|A_,0^Aï(뷟9 y.l|{GQ=6rl!(栉:;*B'Oߌ q{NN%xܣ[kCj@"mcjLɌy[ V]e7қǵٕ 6X4W$DrK ?$WRyv=I S o JlE+ xO7ܕ$7^\33_hܭ§^%h9y-J\y{@[\|Y Je 䞬8Py|͞<dh/Lrҷqf_,zmn= FCz^E=3Txٜ1Thut =̪|<z9WE!Me=`*ي$)i/| }5B>^?2 endstream endobj 184 0 obj /FUQUDU+CMSY10 endobj 176 0 obj << /Type /FontDescriptor /FontName /FUQUDU+CMSY10 /Flags 4 /FontBBox [-29 -960 1116 775] /Ascent 775 /CapHeight 775 /Descent -960 /ItalicAngle -14 /StemV 40 /CharSet (/arrowleft/arrowright/bar/braceleft/braceright/circledot/circleplus/element/equivalence/minus/negationslash/periodcentered/reflexsubset) /FontFile 3227 0 R >> endobj 3228 0 obj << /Length1 1394 /Length2 5926 /Length3 0 /Length 6875 /Filter /FlateDecode >> stream xڍtTk.(0 -! ҂030 HHHRҍ %?wZY^vV-]^KTGrF~~A>~~"vv=]t!+@ 6y0 T] AHD$*w ),|UL.p@¬mP68!\Ç~dH Q6PtG(AŁ@777>3i-CtP+ 0@gscEXH(mApgt tUP`?_ٿ ࿓ V0{(@SQz-|+f@9( 9a AOYn)ppQD'CB!{lp{u-~tq>Ü\*MDج(0C!1 upv~|+4 #rB( ;}"0 `6CG&h~y{%nO5tU4x OV x CTL2[.OE-8 4h.CPߔ_~;_U_ )vsn4]PhY#wա0hy ÜaPK- bHj!a8,~UCU 킢E pE`$Aď&0 %7@>8N1H_kEs舄D* qA"t߿ϿUC!Dȣ`ۊ27Ŧ8pa+/5t'疥wR f;t7m KVAa(t.~8n2["譇DS"㵙n?71h03DMpZUm;k2*F&i+ʈmkdJK4IuSy:t=mX6M띝LX8fRPU}pGOOWzI`,p(QߴtT:?: 6bˊ>ӷ)3gt|KC2ra5-α^6EZ,4: ;rw &ҕ1e/ 2p?PX7YT7TV? ky\r̞7VB업gZ}ET?czm9r@Z-}$$.ʷ+kѤU5_X!-E,0߭!\iX^f6d4M[}g0<ϭׄ?4_P&S f0~aU'=Uzq#]ĹAA_[9?zds rA] 8jGdb"T Nos)xg*9^ՏNt0v/-U5]y0_6~E  P8ouឦ-lBVXˠ_ rk 'X{N 63]^/`n 5{{ΜPTʝp{g,+{&JVi^f͙2 8}$3"f}4fʻ!&f!|Gw.!8Z{i7lE1B) $7}rƤ?OEmYyzIG>e d 7VE#zɚ_D >f%Rɒ }E#L# 1OIN*\x,Z'6_z5 ? KKTxO8|Li'%:O eiB9ݛO?9}%J.N69g-5n5Pڨ0:[-ERHhcS=eW(_$ fdOtދdgn<(1al8+{lk|WbǖCQǕĿ/r®,{k" 's>Fg>p$ZotUe‰qꕩ¼< TߙY0}}c蛷#S70Fcfi(Ksp ~`dlqIDP{L׳BiwK(uՏ ,N[y'nGfߑ҄HtmpnRD?Tq~zl'~)ti0kq)=ϛH' I%`Vإsӓ]\Z=4'>_0%x}6k< ]`7R ͎!L} {H1-%އhQe7A9{r 9S R'j疴}.!8/% t_ 07T,#h|H ȐQ<*\bg$h%3niS]'w[ 8u&}Jn.{x17+̕J%eLMvUőri9m&4{ŭ2|^ӕiPdbyȸY 2ºmH[;>ET@vFIqcP'wd ,,3r_n齅Ws;իq$ ذ@]J'fcV<\~/S/X U$VaelwkZ|~~g] :OW$RvzPS޽x~︐ˉZ$U-a9~@ڼBZ,4Vg4F``(wé"Cқ4&a2\ b 9_צAw:wdr_=#)1 rlPoWG1_G}E.ߠW5JcK^Q}bc|u ~FD"+"xMj"r$u$ R$ܶ5jq[( I;LF{oA{:9]3Q$s܄/;qt#ر4?/쌚4Z%a!MuA3<Ä;[J7hPǠpQLp qB肳^!5Bx<|*<*󈰖fMIiv"0iݘ\,s c&1Ɇ5ƀ@eC5sDOw!LMOƖ*6]K-QiDR"}ͩž_z|sg_og] ;[֎kt^FTTGZoyG;C)QMS h lXI0Qt~^f>f?yJⰹhi(eLG~4J;F"&~}} և/6my %רz'^yqޣʩjw_q^_U Wh:ߐnw}{G޳-c9oSW~qD i9[`}a.b"tJYrS~Yz(^{g;^av<ʚdeW7GJ4RJ8qg 0q5_F tF}fI*6wիbaa ..V(}p1][h%);tCqzg t@8pdShhmoH^TfF͔k}|R~Ւ !Vo=vR4 T>Spk=aui8nwyMxu<$9#ȒJs>Nq5I=y5S򀟛r,]+SCG~S:&몘Murԋ{_x g HFT08z a|]us#z`7'=^J fQD8}G&hy+>p_X:Q lE O4`'=hi;I%$fS n]~[NLhܟgÎ 5T[7xw12Զð=$G3ҭOjmy )o-)L3I 99ke' dovj"6Vy#y_!]/ uE)V>F_7N2yb 3n]A t !vQwt~ 7h{rߵ9T 5Iw)}Izt B'/rcW $.6`!-Hʗ Oz/N_Ys聫3 3 PRa$#h_O^rCVnlaWlO͔ZO~agejX//& Lt;"m_BZ@=.]\Yi?#Qp2l (~=ƿ,UcmI,j7M%/9~QBy֦λs0Dlaا/IO ?@TgxhDcsG *EeZ22>i)K ǟOo&5ws׻ ypST1ʵHO}ͦfܭd- o$ +(ʨ3b}ִiF4GVI.FcR#Df ?T3'׮2Fǜg z~%ׇ"]6/-ɻN#,˦Ȼ4h;ƺrbLEE%~q瀳NQ ,h'Zw%ϜlfD̲l}۰ך]CЙ(`yЮw<2KqQ3^A 7Cr+hFQl"j]R+Ťh hr`psTOTXFb &Uf+H%I'r=&Yl}^啅ѣ*hmΒ*Zw Ξ*Y}f_T,F(ZbPkWh'Aa`_?x)Hn|TUU5lݰN.浕X}*.)nb֡Z?3 RRxK@0wj^ήM^2Ęx3ₔsFƜLvq3=̽\˱r3|x{CA!f[,PH^8Qc$eŗ|MpV{)[Bw7R{"$]ORmNIu$2gwElA| 3nʯ TO '#8^G.wϽ7-ɴkz> endobj 3229 0 obj << /Length1 1394 /Length2 5935 /Length3 0 /Length 6885 /Filter /FlateDecode >> stream xڍuT6-N etctJ#- ۀlS@AIAZB$$DBx~9{v04V((,T7 0X cĹ < F5 ԡ8|>pED`,w #Tz"@}PB`گf&7#OU e%%2@iiY`ge5"\OEm=(~xC ?4 ?ԷKa/oJgB=\\~7'Oe^h8Pj-e}^m/¢ o;{鍀"q0D{.HE|UsƿUr!w_  >1I) xY')@ çh Z%d"n$> Wi/}rLaN/ÛTX'd-xw)Ks]>Z_qVo붜4'8-ޣ6 8aP:=ffu#v劥³첕XO͑Ɗ{۲FgҚ:06<#C&63,@2̼J*cKafxS%UW{5w1mx2\zpvmeVH䈎0V|Sp牾+iE>rZ J3Dd~>U8HPGʵMw{""iʆÛ+[Z5{LQЮB[ůJsn0KxV{Ivލ!eAIb] 2"Db{#zW={`&kYMThW6&ah!Hc9c ,m>C$+CpII̛5vI:ga{+%^q V yegJ%m`R\=H%ss+Mfov' d݌ݦ6Ec.GopL.ot;Od4?8r͒-v6f)D/=)"Tjf0f8" Q8qF˗p@5e؁[[БK/ OXbf(O˒HA@:M;r7-%n=#NqvS8&7{ 9,K:ك欂 G5'mI:j𓴷 ~@GcYLeҫoݡ~>p萭まJ 2-~z\aN3 [n4\& HS%#%(\v- 38{P<0l1GɲۋpR2IB1BCc$d0x{D`Tl,b)봧oͷشcC!JЇFu2I&bwn칰]=/kg &%aE͆~&mhM]tai̧1C( K;g7~QWBE$7R9$ n "(cκ[ ˽3ZLiR;D! 9X q]vRꮪ⛌9f{5>;nQZ%MnՏgUѭT+ q.yfF*:b 3tVxEqCؿn?4<mOxuӓ$ _R 40NcEO\փ+Y;\aeG~3Z}<~ZJ2,0,!Φy3KG1C,jRk 3@i󾱱4TБ^}u1aB*tk܈xN<+NV;Ac{}ȹ?4HEsg!Qtʊ׮[/_v۬E,B I6]Q.:񄖻{w"w[Qk4'* W.W΅6Clɴa [DK MWm&*VQè(>~^@SnNV SI:=mxۤ {ˬ-H L/UqDV$3߾5'Yv/'Ofh /##ؖ) ܢor$>j.9G6iyKXg"jm"hW|c. 7I 'WX֓Ll4ٻHnJ~'dY_wJM_]g6>}8`>/AMUrKCqÃܓM6$/n쏛PEQ$0>/i7ΈD*X!.Z}9eDt겹R4kS*dX2-0o<=4C 5K 3ezh._B݃[+&n 7h$?5?^jԡFzO<:Yr—f[F聁| e6IKM.Q8$_ H'mvp~zr} z5HyBKtRuQp^%m" 'BӾWZYT(٣Fb@h$S츩Zߙͧ;sQN5KFjun((*[4`䰂Yaƶf?>N9Q];hUȐ^v#6 rchrɖ|#_7?vҥt;CtA5},UnG?K+kYvꅿꮳ "u>7est-lҒ4{269t6-/IKQ/Mle0KahU6xMyBqek0fwtRz y ˌ|ֶJ3iN\S]RY|sˆ#x (9b(i1_mnW"'K 2 b^@``P]ueԘLȭ:Ӽ~Y :^<)Lrb8:߻'f|~w8-?+;;YV[dž[c-$lM\MT FvT}Ua %ICj0X?*g ze]#t>^RD ,#r")x 5"VЌ(>Ŗ[$/lw[h_h{.'5#ļ!f  L#=Kt97}d9sإّtUՇL'ʖIW/zR vZ=U ,I!=&K%V_XQΥg:OY%ZR'r~&)lܪ::^ߗQ$,B>[}[ tHD:DԑQN$ 5JC&ӈ9$*9$m}ŵ>j-fj%rlbGU,E(w6lo,#.K}fp` yq`fjy3fՅY|͗^z=\I՘cFɔ ]t;,cd3XHK_jC5/s'ȇk!΁ e)"cɇng1zyi^&Z-M)}": Ms (nj:L H$-zj~dm4m:'J6\dҴSWLFyE9n3'گ囓nqC=Ysjȼ.[F UETqǣWГ(k?-wcS{8zrKUKXC6QU*dPQ|<_WgWU WO' } 8 ^n}OjȗfAnQ4GR_}Y-oUX'\E~kHroG8ח ]=fԽU0IZ>fOM5VGͥ;JPTS0G2s5{~5pF<*(9{Yt>ޅyS3^k7 d"(cI Nj$ry-S_xyHy&܇f! V>HɢkW_tq]C(?bx؛}۷L]ٍkyGTo;5<]&lͭX&\TQx` )XJ=w X?c OJM27ݴ_ QI6h-ع消/ގ햫Q~+f"Q޻&T絈aL>M O>)SxÝZ.CpK^0j&p8K *RDžR.'3C*f}pj_s /z EI}]DWv>R&=!9[ͭMFl ܂8aM婒=)%hP[ܳdէcq`,9ļH9!X endstream endobj 3230 0 obj << /Type /FontDescriptor /FontName /NLXUWS+CMSY8 /Flags 4 /FontBBox [-30 -955 1185 779] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 46 /XHeight 431 /CharSet (/prime) /FontFile 3229 0 R >> endobj 3231 0 obj << /Length1 1653 /Length2 10002 /Length3 0 /Length 11073 /Filter /FlateDecode >> stream xڍT-wwݡJAbRiVܝbŊ(s9{㽑1̥{=f璳Z878@A+ˏd;c2``(D 0dSŸ3O','" ; (=-n:rdR>ڰD8Lȹ`` ;\:P0_%X%pWq///n;7f/ z wd 2@7&/>Og OjW_ 57߿G!0d Cv`g@GY !ݡO@O hсeÿpwnwy(4f%cq>E0 d4w. [?hzBn 5ſbLك!^^^Q~ q+O''~PW P0P?0`8d`d/t07I~|?>g0[(?^1_픗z\!0 ࿫ vPؿ(CAZg--jpӆA=H2d 8᩺3҅xo\|{Z97t6;*Al0}0y/${Q[pCǕxDJݓ`Q<0}lϰ`ۚcfE=,fY 1p݀Վ)#UvUWдV4K,iE27l,ΏW_Xt'gd>Oe$U*dl ef`?Ə.ʽ+JiץuP-f +kF|%5[ֺōxVuaRA"&cɹҼG)]'Vץxyh}]q/638^_zR3?lo3O~N].[,#:{}1ӶU4#@7;ChI1ۻbé_oPKW3i݅ReYBcۂ8EiDlSQ#<nQ˓{՗|pЯ+eq>Q|QԓIz4 2-;g OAnN@l*%ۛF!1Jޡ,-%BQ6ARv/s6Ļ^|رwW9j]>M5F/$m2uJOthYYfkFpJAY,'#STEؖD(Ҏ rPYR#pu׳Cn&$Vu]f9r}W?%fِE[ Xbzb2SVUmv%X\e(|V@{~&sCf@qgym_6F՘e9AO 8j2Kj F tz\Ì4^ĐqҺ`vSlK`Ҋ5|%KOccE: [iMWS\k/Z_@_WVeΚ %I,Ky2)CzϳKS[P`IvXUyFX5W_7ҰG{C &#+v"[[ZwQ޲lu[9XvcĩBT߀4|$2x'׊pbn3$=b~RD*Rj׼}Q&װcP&!_+F8!xLCcj݌+!ڨ܅^γB,#+n]Ѿu mmȥY3471Ɓ9d.۽[d$n4@/-x b׫zL(^!k/?9IwM+ |lB"˯|9Z&wP~vg2;.x'+"P TFgzCM?o7'lG8ta?'/6CP9bv+F0E΋vR\)M2`'O7&,o0="nvpMm58MQK;V5I^Ta8*ꏾ<ٻ,fao2i毽7z.)W҈p}ixYua4N (hku=)ͨT{$-JYA)xBp7Rd:MN=T%n3d548Kۨj ?0^| }(bxh4ӀV҈D iƛ{S`hh8]CqOP Guau(3wx*ٿW>lYJ,;uZ&~Ga$qʹ3Qٛ={:gX1{}JBsWngîouw&D"O&|o׌ AJ"Ո83~d5I;Ga)Nf=$Yli)?N;NJ(leS>;vEQ~`; (2˴BD^,"~^a6QQy $zިc8~d_ /UFaFƀcU>-=c`5S9gb,r*u@ST7Rĺ?<2˝Q;-i翇P$Zu- ՟4!v)9m Se}X~734^u`KQ;C 2e< b.?%MzԑB`uGh1Va}hoA5UkWi65I4|W3iҠ2i=_oE?1 Xֆ01 uS^ 4gТC]yÍftTѮڌ;- /CokHSfv7 SX3|-T-}B &e#L?EP(Zx ٣P67#m$x%m"JPo!4f~xθ،:lRUcHv;r\VpqL0ᔢr샸;'-;(*mgB+x\/hZϐtqV@XDIK+(f"X$hHA,f kq` /\HfL.k%X΋&YINt%҉Ģ{a\jG z 3Y"oZz՞'û5J{g!̩R箘jh}QӗrtGt[I8kVQqDLѸ ?XcL[ڹ52x\)>h%U,~VLjnICamI׶%i];BĵH-B ^E;=F)]0ң{I(C̤KLp撄Ry~E~RwUud#`ZGM]NUgk?^y u&`4L_:zA/.oj`Z@jgL )@#ɚ)hy86)xOg[-iz*7WHqޖ-;ݎOoqDCH^_<^"S |~#̳l# 6 !"7ǒ 6w5h&a7ZU'\`{D`5U#Oa YKU,{j+uP-56Puޘ+$1\5%35Ц-f4'FelpEsĔP)ғbp pVͶ`/L3.g Syk 5kr 릂hU ?>3eZwIyE6( }a`,1[&|l6zW=- 96/J}8;[=B$,7kD=N k Ϛ&3:;<,HVt3'_:h[INDߪ!2pF1pME9WX&{ָB6TWa[KIz>*!Zj\jG|ϳ Ŏ3ßW&߭6ذ r,+Cl#&L=2uC=3wld^k9 A{+?rj_ˍ@$[-=s`,3?,}iIIQ9=0Jog|c\t`1P(XE„7gMqŒ8btH/޼8|cjUcJr֡pdH^btbCSlNuGrE 2 6QyӜ $v'赻m#A^-Y cb_տ:t,_YĢ-ꅧńơ$3z! iWqzTbU ex?(ׯbk54g/d(K`-hrs}7mI@P1aYe 򆺸c@A?vbB'd`TL$0q|ЏFk59@s RWEx}.JYMsg7Xc'VFaCC >{%syF T3ҟV6y?'6Ә) gE| 8 ƑunU \r E']b'kRSlN_5VAI`UAǢ o}o Z(k_Ѳxiv nq82!{h[yf5_S3sFUDƟjhS1 KœTTǬFHxbI5d2HϡLY9{V-پ6ENyr@,Zg/zH>wi{1 ## y-ƶiIswew!#xe% _j)spG*{eD-5 ڱ֦?ǧӴ硊9 [!'5x/Y󎓼 B颠ujj/޶Х. RثGc0Vm>MM4.Nu!0{܀X PZe7Y2Iؚ{/,@µ-&[!;υσke\dz+H6q&\I(~Joy^ʝ'lVE>ߘҋ%\xo[kFWg<ƾԿқ }%"2+߿/QŖP6!2?4]E=dfnl^$D*iȳo @X)F;˭F~K*J(EgOݢM 6CAѧ\8践SRid:!H0S)qA;b_S*a\"7r8ɄNKK7qoK#L,:-wIOZHak [W #onuHjۼn]M`%6~aG)}TY/Nw#0 ~w0vTőr2g"`&J$T6UR\D Y!=d*eXubvkc ;5/0P,4  n#bSO:mf#1'dŎ׆`;9 ϩߩs qD 9>3o3Ρ{yRC=Qz`Dydȼ:XeAn34K c3jdJ ]%$ ^+ycy`7Hms*A plL\L.yQ{IE 9t.O$Jp uq'bՔiL G]^yL.6*4#{2کQ/X$6-kosȘoLcivo1Ϩ.muPK{/kuCq.Sft"WH9my-kj Ǒ~9ݝį%:/ʏqACic{\Y.^"4RI`c >i^gtqY+ɌB7ςE,PVj|z(je x(ߌ(wCK_k烟lU&l188+1TI{A$'Zq2* `mFsI~#EZxL c#sHO I/Б* .β֓<[n6Ϲ7 (?YmFMe8̫{DT ٔ Z[EW}޳b}Pܠnƨu*%duo3XcN倭_ Fr}@5؁pxA o5ksz|(9f~&X"K4ؐ.Dt\P~4?&hEIr:]~m6rb`ME-F|&iFf5,x(EB&vvB2#Ru^,ꩀpMNJujdPfęVB7wq]sSKgA`2ɋ@RlJA%mKR@ F3+w8QO^DXoewqгh@p *ɭ}SŸXr9JQ{~S5 w0@dv*5&ܫen6Wgެ,kB&oGx~c-I^J8i t?o<?R`^$D`bs v`[_{P"HVM9ȈwBe;5Z Ml7vΘIE L&# gJX3s2ilED 4v[ s)~{#d3wklTG7lFg7R}bP&A9z oTyCޚԿc@?DԊO1}G+x)\`%Rf!1Ae5|2"/ImyoQЉ\Lnʩa7¸*_kDE;꫆O0*؁TLp&A$JSE͑:ȷamc]G>"z愹j{v8jߐdwֱ:y+EXeKZ?0q& K9d`w؍P fOs~7L>ޡ5Ͷ7"ppr4Sk՞>߀`􅈡;>V fbaW5AtG[$S%4FLH b4.&1WsJB^~PV84TNS%cpTv١ n*Oyw{7s+(5R`pKC e,l'FQ:f{4Sstm1Ķ!ͣ=Z.ԟa9B&J][7v|d 0wۋz$s9GKK䅐V3˸~R4-?Udൊvv6 D`3WؒbYeCg vz !cGћ&-]An#(m^zz`()f퇄_:wcrW'W ~Q$IR0R"L~\|oh= 8f绥o.)ѦLñf)"kTR9~8p*єZu/<]TߋV٠?޺;fV:!+:ȐjTs3r&cK{?KW'1:KltKؗ-[ ׎S*3b@ƳlG^ʬwN~zhoWGA' Vddjt hFsmo[]- ݶ櫘sqևʣ9RvZ+Wav%^OcBő>Rbڔ$0[H2~D 9gAܨv˄Nv_Dzζ?ǦQOdEF'^gfuz_ >wʡ<`5]Iiu> endobj 3233 0 obj << /Length1 1328 /Length2 1591 /Length3 0 /Length 2446 /Filter /FlateDecode >> stream xڍS 8TONAWuNGO)yQ#Jq1{1"x8$Jo:!upC8 Q*!=u{=Zo-6bA0Cq3jܼhT@2T*ddBdH  !9B `Lh @-RJ$V#\F10Rq+9&fit,؉` P|XDT@BqW~˜qP(ȐHJ$+ML 9*$#Go+ \Xu-8x8L4ȴO&Ut,p0B xd<7U!#!9 0t`8Oʑ b\J"BG* f'뀉D0KI9"C]IhA< LLE8!L϶`L*frUsTfCDA@x0G BrF\ 8AIf7~'/ABf*!?~N¸*T~iON{{,1̜Na!<:B&^EFW$}$"Pژ+ca`YT&C|h7OElP87!B8I&%l "2߽8Dl,>DFBa'sN|r0jyL I$D%B'F# P(!@,#T#YPU&Wi92ؙ5?CaƱz!`|ًwq};͕r`eo+^ѳFP?> O|^Pix,Wҵ2zۚ762PnW(lM7 yѐZ|% vڒ]d5tW`hM.K/η?oWum$}v{t柷昪!|-^ӗrejGż5y~㨾ёA*o7!ot,k i jэ[nn3g%#^ļiڣ;&4}[u\+s`qX4Y@+ J;{u"{tjp24ry'.0s;ho?E/>;odt0[ЗC +FT/ͲoXĬb\tIH=tm/#e2)#-ʢL]3<խzvskqjGZʎ]- Ry]smtp{.]ɪ`DuJFnb?hsM/@_䓿d߷˭Iѯnx+N>Jl6_tXt)^5*#>3i'f<ҋ{j~[<Ͷ7Vڗ_<+sv)ʺMg]R2sp,u%syϻ|uRF}P ˉ>43uuLof⭜{6zwSVF+0ţ$lݦ̆3lSfcRĶ]:}O䋙/.zʖ:QoR:3|^IOG5:'+sUѷXTYe=IqlA5dKOikDtnwSV ڮh]yaUdmѮce2X|kwTk)ikI|,0 aCmf;b:g3c-zV&yEķz:4#,5{8y괡gՏ[tݔcIg)Lݗ7],6>1 uzmL֠=?m ۣӨad.mF e%.'ʖQo14PnxX:NI_tnwÊ' ~)z |ܶFj<"›i9:mūHߘo5 endstream endobj 3234 0 obj << /Type /FontDescriptor /FontName /TZYURE+MSBM10 /Flags 4 /FontBBox [-55 -420 2343 920] /Ascent 464 /CapHeight 689 /Descent 0 /ItalicAngle 0 /StemV 40 /XHeight 463 /CharSet (/N) /FontFile 3233 0 R >> endobj 703 0 obj << /Type /Font /Subtype /Type1 /BaseFont /BZYULN+CMEX10 /FontDescriptor 211 0 R /FirstChar 80 /LastChar 80 /Widths 3195 0 R >> endobj 1317 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VAFDUK+CMMI10 /FontDescriptor 173 0 R /FirstChar 11 /LastChar 62 /Widths 3192 0 R >> endobj 165 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EZFLEG+CMMI12 /FontDescriptor 3209 0 R /FirstChar 59 /LastChar 59 /Widths 3197 0 R >> endobj 2588 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VGUMHO+CMR10 /FontDescriptor 170 0 R /FirstChar 94 /LastChar 94 /Widths 3189 0 R >> endobj 770 0 obj << /Type /Font /Subtype /Type1 /BaseFont /JHEROP+CMR12 /FontDescriptor 3212 0 R /FirstChar 97 /LastChar 110 /Widths 3194 0 R >> endobj 42 0 obj << /Type /Font /Subtype /Type1 /BaseFont /JDIDFF+CMSS10 /FontDescriptor 132 0 R /FirstChar 12 /LastChar 127 /Widths 3203 0 R >> endobj 41 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XNSREL+CMSS12 /FontDescriptor 3216 0 R /FirstChar 12 /LastChar 127 /Widths 3204 0 R >> endobj 79 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IZCVVU+CMSS8 /FontDescriptor 3218 0 R /FirstChar 43 /LastChar 102 /Widths 3200 0 R >> endobj 43 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RYVCTC+CMSSBX10 /FontDescriptor 3220 0 R /FirstChar 12 /LastChar 127 /Widths 3202 0 R >> endobj 1612 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NNXMST+CMSSI10 /FontDescriptor 3222 0 R /FirstChar 14 /LastChar 121 /Widths 3191 0 R >> endobj 164 0 obj << /Type /Font /Subtype /Type1 /BaseFont /FUQUDU+CMSY10 /FontDescriptor 176 0 R /FirstChar 0 /LastChar 106 /Widths 3198 0 R >> endobj 2515 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NLXUWS+CMSY8 /FontDescriptor 3230 0 R /FirstChar 48 /LastChar 48 /Widths 3190 0 R >> endobj 3138 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VYPLOO+CMTT10 /FontDescriptor 3232 0 R /FirstChar 46 /LastChar 117 /Widths 3188 0 R >> endobj 78 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NNXMST+CMSSI10 /FontDescriptor 3222 0 R /FirstChar 65 /LastChar 121 /Widths 3201 0 R >> endobj 163 0 obj << /Type /Font /Subtype /Type1 /BaseFont /DJLTJK+CMSSI12 /FontDescriptor 3224 0 R /FirstChar 120 /LastChar 121 /Widths 3199 0 R >> endobj 605 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RSYDMR+CMSSI8 /FontDescriptor 3226 0 R /FirstChar 105 /LastChar 112 /Widths 3196 0 R >> endobj 1316 0 obj << /Type /Font /Subtype /Type1 /BaseFont /TZYURE+MSBM10 /FontDescriptor 3234 0 R /FirstChar 78 /LastChar 78 /Widths 3193 0 R >> endobj 46 0 obj << /Type /Pages /Count 6 /Parent 3235 0 R /Kids [11 0 R 76 0 R 104 0 R 129 0 R 161 0 R 208 0 R] >> endobj 250 0 obj << /Type /Pages /Count 6 /Parent 3235 0 R /Kids [248 0 R 287 0 R 325 0 R 362 0 R 386 0 R 411 0 R] >> endobj 451 0 obj << /Type /Pages /Count 6 /Parent 3235 0 R /Kids [449 0 R 488 0 R 526 0 R 564 0 R 603 0 R 653 0 R] >> endobj 678 0 obj << /Type /Pages /Count 6 /Parent 3235 0 R /Kids [676 0 R 701 0 R 729 0 R 768 0 R 805 0 R 839 0 R] >> endobj 866 0 obj << /Type /Pages /Count 6 /Parent 3235 0 R /Kids [864 0 R 889 0 R 914 0 R 939 0 R 973 0 R 1007 0 R] >> endobj 1045 0 obj << /Type /Pages /Count 6 /Parent 3235 0 R /Kids [1043 0 R 1074 0 R 1103 0 R 1128 0 R 1153 0 R 1177 0 R] >> endobj 1204 0 obj << /Type /Pages /Count 6 /Parent 3236 0 R /Kids [1202 0 R 1237 0 R 1266 0 R 1290 0 R 1314 0 R 1341 0 R] >> endobj 1366 0 obj << /Type /Pages /Count 6 /Parent 3236 0 R /Kids [1364 0 R 1389 0 R 1415 0 R 1438 0 R 1462 0 R 1489 0 R] >> endobj 1515 0 obj << /Type /Pages /Count 6 /Parent 3236 0 R /Kids [1513 0 R 1537 0 R 1561 0 R 1586 0 R 1610 0 R 1637 0 R] >> endobj 1662 0 obj << /Type /Pages /Count 6 /Parent 3236 0 R /Kids [1660 0 R 1684 0 R 1708 0 R 1734 0 R 1757 0 R 1780 0 R] >> endobj 1806 0 obj << /Type /Pages /Count 6 /Parent 3236 0 R /Kids [1804 0 R 1830 0 R 1853 0 R 1878 0 R 1901 0 R 1926 0 R] >> endobj 1951 0 obj << /Type /Pages /Count 6 /Parent 3236 0 R /Kids [1949 0 R 1975 0 R 1998 0 R 2023 0 R 2048 0 R 2072 0 R] >> endobj 2103 0 obj << /Type /Pages /Count 6 /Parent 3237 0 R /Kids [2101 0 R 2143 0 R 2182 0 R 2221 0 R 2259 0 R 2295 0 R] >> endobj 2322 0 obj << /Type /Pages /Count 6 /Parent 3237 0 R /Kids [2320 0 R 2344 0 R 2370 0 R 2394 0 R 2418 0 R 2442 0 R] >> endobj 2468 0 obj << /Type /Pages /Count 6 /Parent 3237 0 R /Kids [2466 0 R 2490 0 R 2513 0 R 2540 0 R 2563 0 R 2586 0 R] >> endobj 2615 0 obj << /Type /Pages /Count 6 /Parent 3237 0 R /Kids [2613 0 R 2638 0 R 2662 0 R 2685 0 R 2709 0 R 2739 0 R] >> endobj 2775 0 obj << /Type /Pages /Count 6 /Parent 3237 0 R /Kids [2773 0 R 2804 0 R 2834 0 R 2859 0 R 2883 0 R 2909 0 R] >> endobj 2935 0 obj << /Type /Pages /Count 6 /Parent 3237 0 R /Kids [2933 0 R 2957 0 R 2981 0 R 3014 0 R 3039 0 R 3062 0 R] >> endobj 3090 0 obj << /Type /Pages /Count 5 /Parent 3238 0 R /Kids [3088 0 R 3112 0 R 3136 0 R 3161 0 R 3185 0 R] >> endobj 3235 0 obj << /Type /Pages /Count 36 /Parent 3239 0 R /Kids [46 0 R 250 0 R 451 0 R 678 0 R 866 0 R 1045 0 R] >> endobj 3236 0 obj << /Type /Pages /Count 36 /Parent 3239 0 R /Kids [1204 0 R 1366 0 R 1515 0 R 1662 0 R 1806 0 R 1951 0 R] >> endobj 3237 0 obj << /Type /Pages /Count 36 /Parent 3239 0 R /Kids [2103 0 R 2322 0 R 2468 0 R 2615 0 R 2775 0 R 2935 0 R] >> endobj 3238 0 obj << /Type /Pages /Count 5 /Parent 3239 0 R /Kids [3090 0 R] >> endobj 3239 0 obj << /Type /Pages /Count 113 /Kids [3235 0 R 3236 0 R 3237 0 R 3238 0 R] >> endobj 3240 0 obj << /Names [(Doc-Start) 40 0 R (Navigation1) 44 0 R (Navigation10) 340 0 R (Navigation100) 2837 0 R (Navigation101) 2861 0 R (Navigation102) 2885 0 R] /Limits [(Doc-Start) (Navigation102)] >> endobj 3241 0 obj << /Names [(Navigation103) 2911 0 R (Navigation104) 2886 0 R (Navigation105) 2887 0 R (Navigation106) 2992 0 R (Navigation107) 3016 0 R (Navigation108) 3017 0 R] /Limits [(Navigation103) (Navigation108)] >> endobj 3242 0 obj << /Names [(Navigation109) 3064 0 R (Navigation11) 364 0 R (Navigation110) 3065 0 R (Navigation111) 3066 0 R (Navigation112) 3139 0 R (Navigation113) 52 0 R] /Limits [(Navigation109) (Navigation113)] >> endobj 3243 0 obj << /Names [(Navigation12) 388 0 R (Navigation13) 426 0 R (Navigation14) 465 0 R (Navigation15) 503 0 R (Navigation16) 541 0 R (Navigation17) 579 0 R] /Limits [(Navigation12) (Navigation17)] >> endobj 3244 0 obj << /Names [(Navigation18) 630 0 R (Navigation19) 631 0 R (Navigation2) 51 0 R (Navigation20) 679 0 R (Navigation21) 704 0 R (Navigation22) 744 0 R] /Limits [(Navigation18) (Navigation22)] >> endobj 3245 0 obj << /Names [(Navigation23) 745 0 R (Navigation24) 746 0 R (Navigation25) 841 0 R (Navigation26) 842 0 R (Navigation27) 892 0 R (Navigation28) 916 0 R] /Limits [(Navigation23) (Navigation28)] >> endobj 3246 0 obj << /Names [(Navigation29) 950 0 R (Navigation3) 82 0 R (Navigation30) 984 0 R (Navigation31) 1020 0 R (Navigation32) 1051 0 R (Navigation33) 1081 0 R] /Limits [(Navigation29) (Navigation33)] >> endobj 3247 0 obj << /Names [(Navigation34) 1105 0 R (Navigation35) 1131 0 R (Navigation36) 1155 0 R (Navigation37) 1179 0 R (Navigation38) 1214 0 R (Navigation39) 1244 0 R] /Limits [(Navigation34) (Navigation39)] >> endobj 3248 0 obj << /Names [(Navigation4) 106 0 R (Navigation40) 1268 0 R (Navigation41) 1292 0 R (Navigation42) 1318 0 R (Navigation43) 1319 0 R (Navigation44) 1367 0 R] /Limits [(Navigation4) (Navigation44)] >> endobj 3249 0 obj << /Names [(Navigation45) 1391 0 R (Navigation46) 1392 0 R (Navigation47) 1393 0 R (Navigation48) 1465 0 R (Navigation49) 1491 0 R (Navigation5) 138 0 R] /Limits [(Navigation45) (Navigation5)] >> endobj 3250 0 obj << /Names [(Navigation50) 1466 0 R (Navigation51) 1467 0 R (Navigation52) 1564 0 R (Navigation53) 1588 0 R (Navigation54) 1613 0 R (Navigation55) 1614 0 R] /Limits [(Navigation50) (Navigation55)] >> endobj 3251 0 obj << /Names [(Navigation56) 1615 0 R (Navigation57) 1686 0 R (Navigation58) 1710 0 R (Navigation59) 1711 0 R (Navigation6) 185 0 R (Navigation60) 1712 0 R] /Limits [(Navigation56) (Navigation60)] >> endobj 3252 0 obj << /Names [(Navigation61) 1782 0 R (Navigation62) 1807 0 R (Navigation63) 1808 0 R (Navigation64) 1855 0 R (Navigation65) 1856 0 R (Navigation66) 1903 0 R] /Limits [(Navigation61) (Navigation66)] >> endobj 3253 0 obj << /Names [(Navigation67) 1904 0 R (Navigation68) 1952 0 R (Navigation69) 1953 0 R (Navigation7) 225 0 R (Navigation70) 2000 0 R (Navigation71) 2026 0 R] /Limits [(Navigation67) (Navigation71)] >> endobj 3254 0 obj << /Names [(Navigation72) 2050 0 R (Navigation73) 2074 0 R (Navigation74) 2119 0 R (Navigation75) 2160 0 R (Navigation76) 2199 0 R (Navigation77) 2120 0 R] /Limits [(Navigation72) (Navigation77)] >> endobj 3255 0 obj << /Names [(Navigation78) 2121 0 R (Navigation79) 2297 0 R (Navigation8) 264 0 R (Navigation80) 2298 0 R (Navigation81) 2346 0 R (Navigation82) 2372 0 R] /Limits [(Navigation78) (Navigation82)] >> endobj 3256 0 obj << /Names [(Navigation83) 2396 0 R (Navigation84) 2420 0 R (Navigation85) 2444 0 R (Navigation86) 2347 0 R (Navigation87) 2348 0 R (Navigation88) 2516 0 R] /Limits [(Navigation83) (Navigation88)] >> endobj 3257 0 obj << /Names [(Navigation89) 2517 0 R (Navigation9) 302 0 R (Navigation90) 2518 0 R (Navigation91) 2589 0 R (Navigation92) 2616 0 R (Navigation93) 2640 0 R] /Limits [(Navigation89) (Navigation93)] >> endobj 3258 0 obj << /Names [(Navigation94) 2590 0 R (Navigation95) 2591 0 R (Navigation96) 2716 0 R (Navigation97) 2750 0 R (Navigation98) 2781 0 R (Navigation99) 2811 0 R] /Limits [(Navigation94) (Navigation99)] >> endobj 3259 0 obj << /Names [(page.1) 45 0 R (page.113) 3187 0 R (page.2) 80 0 R (page.26) 891 0 R (page.34) 1130 0 R (page.51) 1563 0 R] /Limits [(page.1) (page.51)] >> endobj 3260 0 obj << /Names [(page.70) 2025 0 R (page.99) 2836 0 R] /Limits [(page.70) (page.99)] >> endobj 3261 0 obj << /Kids [3240 0 R 3241 0 R 3242 0 R 3243 0 R 3244 0 R 3245 0 R] /Limits [(Doc-Start) (Navigation28)] >> endobj 3262 0 obj << /Kids [3246 0 R 3247 0 R 3248 0 R 3249 0 R 3250 0 R 3251 0 R] /Limits [(Navigation29) (Navigation60)] >> endobj 3263 0 obj << /Kids [3252 0 R 3253 0 R 3254 0 R 3255 0 R 3256 0 R 3257 0 R] /Limits [(Navigation61) (Navigation93)] >> endobj 3264 0 obj << /Kids [3258 0 R 3259 0 R 3260 0 R] /Limits [(Navigation94) (page.99)] >> endobj 3265 0 obj << /Kids [3261 0 R 3262 0 R 3263 0 R 3264 0 R] /Limits [(Doc-Start) (page.99)] >> endobj 3266 0 obj << /Dests 3265 0 R >> endobj 3267 0 obj << /Type /Catalog /Pages 3239 0 R /Names 3266 0 R /PageMode/UseOutlines/PageLabels<>1<>2<>3<>4<>5<>6<>7<>8<>9<>10<>11<>12<>13<>14<>15<>16<>18<>19<>20<>23<>25<>26<>27<>28<>29<>30<>31<>32<>33<>34<>35<>36<>37<>38<>39<>40<>42<>43<>46<>50<>51<>52<>55<>56<>59<>60<>62<>64<>66<>68<>69<>70<>71<>72<>77<>79<>86<>89<>94<>95<>96<>97<>98<>99<>100<>104<>105<>107<>110<>111<>112<>]>> /OpenAction 10 0 R >> endobj 3268 0 obj << /Author(Bjarke Hammersholt RouneDepartment of MathematicsUniversity of Kaiserslautern)/Title( Fast prime field Gr\366bner basis computation)/Subject()/Creator(LaTeX with Beamer class version 3.20)/Producer(pdfTeX-1.40.13)/Keywords() /CreationDate (D:20130924160653+01'00') /ModDate (D:20130924160653+01'00') /Trapped /False /PTEX.Fullbanner (This is MiKTeX-pdfTeX 2.9.4535 (1.40.13)) >> endobj xref 0 3269 0000000004 65535 f 0000642459 00000 n 0000642479 00000 n 0000642499 00000 n 0000000005 00000 f 0000000006 00000 f 0000000007 00000 f 0000000008 00000 f 0000000009 00000 f 0000000013 00000 f 0000000015 00000 n 0000001547 00000 n 0000001842 00000 n 0000000000 00000 f 0000003428 00000 n 0000002292 00000 n 0000002760 00000 n 0000004074 00000 n 0000004228 00000 n 0000004368 00000 n 0000004522 00000 n 0000004675 00000 n 0000004829 00000 n 0000004983 00000 n 0000005137 00000 n 0000005290 00000 n 0000005444 00000 n 0000005600 00000 n 0000005756 00000 n 0000005910 00000 n 0000006064 00000 n 0000006220 00000 n 0000006376 00000 n 0000006530 00000 n 0000006686 00000 n 0000006824 00000 n 0000006960 00000 n 0000007100 00000 n 0000007420 00000 n 0000000063 00000 n 0000007253 00000 n 0000836276 00000 n 0000836132 00000 n 0000836565 00000 n 0000007312 00000 n 0000007366 00000 n 0000837883 00000 n 0000002045 00000 n 0000002485 00000 n 0000002955 00000 n 0000003628 00000 n 0000012875 00000 n 0000642134 00000 n 0000009244 00000 n 0000009698 00000 n 0000009852 00000 n 0000009992 00000 n 0000010146 00000 n 0000010299 00000 n 0000010453 00000 n 0000010607 00000 n 0000010761 00000 n 0000010914 00000 n 0000011068 00000 n 0000011224 00000 n 0000011380 00000 n 0000011534 00000 n 0000011688 00000 n 0000011844 00000 n 0000012000 00000 n 0000012154 00000 n 0000012310 00000 n 0000012448 00000 n 0000012584 00000 n 0000012724 00000 n 0000012983 00000 n 0000008949 00000 n 0000007629 00000 n 0000837296 00000 n 0000836421 00000 n 0000012929 00000 n 0000009449 00000 n 0000017480 00000 n 0000014474 00000 n 0000014627 00000 n 0000014765 00000 n 0000014916 00000 n 0000015069 00000 n 0000015222 00000 n 0000015375 00000 n 0000015528 00000 n 0000015680 00000 n 0000015833 00000 n 0000015988 00000 n 0000016142 00000 n 0000016295 00000 n 0000016448 00000 n 0000016602 00000 n 0000016757 00000 n 0000016910 00000 n 0000017065 00000 n 0000017203 00000 n 0000017339 00000 n 0000017534 00000 n 0000014180 00000 n 0000013192 00000 n 0000023978 00000 n 0000018808 00000 n 0000020955 00000 n 0000021109 00000 n 0000021248 00000 n 0000021400 00000 n 0000021554 00000 n 0000021708 00000 n 0000021862 00000 n 0000022016 00000 n 0000022169 00000 n 0000022323 00000 n 0000022479 00000 n 0000022634 00000 n 0000022788 00000 n 0000022942 00000 n 0000023097 00000 n 0000023253 00000 n 0000023407 00000 n 0000023563 00000 n 0000023701 00000 n 0000023837 00000 n 0000024033 00000 n 0000018497 00000 n 0000017693 00000 n 0000019924 00000 n 0000734310 00000 n 0000020843 00000 n 0000020053 00000 n 0000020349 00000 n 0000020596 00000 n 0000734278 00000 n 0000031112 00000 n 0000025407 00000 n 0000028089 00000 n 0000028243 00000 n 0000028382 00000 n 0000028534 00000 n 0000028688 00000 n 0000028842 00000 n 0000028996 00000 n 0000029150 00000 n 0000029303 00000 n 0000029457 00000 n 0000029613 00000 n 0000029768 00000 n 0000029922 00000 n 0000030076 00000 n 0000030231 00000 n 0000030387 00000 n 0000030541 00000 n 0000030697 00000 n 0000030835 00000 n 0000030971 00000 n 0000031167 00000 n 0000025096 00000 n 0000024184 00000 n 0000837442 00000 n 0000836860 00000 n 0000835698 00000 n 0000026439 00000 n 0000718651 00000 n 0000028028 00000 n 0000026568 00000 n 0000702857 00000 n 0000027914 00000 n 0000026723 00000 n 0000677489 00000 n 0000027852 00000 n 0000026980 00000 n 0000806343 00000 n 0000027790 00000 n 0000027143 00000 n 0000027296 00000 n 0000027543 00000 n 0000718621 00000 n 0000702826 00000 n 0000677457 00000 n 0000806311 00000 n 0000038645 00000 n 0000032631 00000 n 0000035622 00000 n 0000035776 00000 n 0000035915 00000 n 0000036067 00000 n 0000036221 00000 n 0000036375 00000 n 0000036529 00000 n 0000036683 00000 n 0000036836 00000 n 0000036990 00000 n 0000037146 00000 n 0000037301 00000 n 0000037455 00000 n 0000037609 00000 n 0000037764 00000 n 0000037920 00000 n 0000038074 00000 n 0000038230 00000 n 0000038368 00000 n 0000038504 00000 n 0000038700 00000 n 0000032320 00000 n 0000031381 00000 n 0000033747 00000 n 0000667548 00000 n 0000035478 00000 n 0000033876 00000 n 0000035417 00000 n 0000034061 00000 n 0000035339 00000 n 0000034216 00000 n 0000035277 00000 n 0000034405 00000 n 0000035215 00000 n 0000034568 00000 n 0000034721 00000 n 0000034968 00000 n 0000667516 00000 n 0000046472 00000 n 0000040101 00000 n 0000043449 00000 n 0000043603 00000 n 0000043742 00000 n 0000043894 00000 n 0000044048 00000 n 0000044202 00000 n 0000044356 00000 n 0000044510 00000 n 0000044663 00000 n 0000044817 00000 n 0000044973 00000 n 0000045128 00000 n 0000045282 00000 n 0000045436 00000 n 0000045591 00000 n 0000045747 00000 n 0000045901 00000 n 0000046057 00000 n 0000046195 00000 n 0000046331 00000 n 0000046527 00000 n 0000039789 00000 n 0000038927 00000 n 0000837998 00000 n 0000041473 00000 n 0000043305 00000 n 0000041602 00000 n 0000043244 00000 n 0000041787 00000 n 0000043133 00000 n 0000041942 00000 n 0000043071 00000 n 0000042199 00000 n 0000043009 00000 n 0000042362 00000 n 0000042515 00000 n 0000042762 00000 n 0000054272 00000 n 0000047908 00000 n 0000051249 00000 n 0000051403 00000 n 0000051542 00000 n 0000051694 00000 n 0000051848 00000 n 0000052002 00000 n 0000052156 00000 n 0000052310 00000 n 0000052463 00000 n 0000052617 00000 n 0000052773 00000 n 0000052928 00000 n 0000053082 00000 n 0000053236 00000 n 0000053391 00000 n 0000053547 00000 n 0000053701 00000 n 0000053857 00000 n 0000053995 00000 n 0000054131 00000 n 0000054327 00000 n 0000047596 00000 n 0000046730 00000 n 0000049273 00000 n 0000051105 00000 n 0000049402 00000 n 0000051044 00000 n 0000049587 00000 n 0000050933 00000 n 0000049742 00000 n 0000050871 00000 n 0000049999 00000 n 0000050809 00000 n 0000050162 00000 n 0000050315 00000 n 0000050562 00000 n 0000062113 00000 n 0000055708 00000 n 0000059088 00000 n 0000059242 00000 n 0000059381 00000 n 0000059534 00000 n 0000059688 00000 n 0000059842 00000 n 0000059996 00000 n 0000060151 00000 n 0000060304 00000 n 0000060458 00000 n 0000060614 00000 n 0000060769 00000 n 0000060923 00000 n 0000061077 00000 n 0000061232 00000 n 0000061388 00000 n 0000061542 00000 n 0000061698 00000 n 0000061836 00000 n 0000061972 00000 n 0000062168 00000 n 0000055396 00000 n 0000054530 00000 n 0000057104 00000 n 0000058944 00000 n 0000057233 00000 n 0000058883 00000 n 0000057418 00000 n 0000058764 00000 n 0000057573 00000 n 0000058702 00000 n 0000057830 00000 n 0000058640 00000 n 0000057993 00000 n 0000058146 00000 n 0000058393 00000 n 0000066496 00000 n 0000063469 00000 n 0000063623 00000 n 0000063762 00000 n 0000063915 00000 n 0000064069 00000 n 0000064224 00000 n 0000064379 00000 n 0000064534 00000 n 0000064687 00000 n 0000064841 00000 n 0000064997 00000 n 0000065152 00000 n 0000065306 00000 n 0000065460 00000 n 0000065615 00000 n 0000065771 00000 n 0000065925 00000 n 0000066081 00000 n 0000066219 00000 n 0000066355 00000 n 0000066551 00000 n 0000063157 00000 n 0000062371 00000 n 0000071020 00000 n 0000067991 00000 n 0000068146 00000 n 0000068285 00000 n 0000068438 00000 n 0000068593 00000 n 0000068748 00000 n 0000068903 00000 n 0000069058 00000 n 0000069211 00000 n 0000069365 00000 n 0000069521 00000 n 0000069676 00000 n 0000069830 00000 n 0000069984 00000 n 0000070139 00000 n 0000070295 00000 n 0000070449 00000 n 0000070605 00000 n 0000070743 00000 n 0000070879 00000 n 0000071075 00000 n 0000067679 00000 n 0000066702 00000 n 0000078223 00000 n 0000072580 00000 n 0000075194 00000 n 0000075349 00000 n 0000075488 00000 n 0000075641 00000 n 0000075796 00000 n 0000075951 00000 n 0000076106 00000 n 0000076261 00000 n 0000076414 00000 n 0000076568 00000 n 0000076724 00000 n 0000076879 00000 n 0000077033 00000 n 0000077187 00000 n 0000077342 00000 n 0000077498 00000 n 0000077652 00000 n 0000077808 00000 n 0000077946 00000 n 0000078082 00000 n 0000078278 00000 n 0000072268 00000 n 0000071302 00000 n 0000073442 00000 n 0000075104 00000 n 0000073571 00000 n 0000075043 00000 n 0000073732 00000 n 0000074978 00000 n 0000073887 00000 n 0000074916 00000 n 0000074044 00000 n 0000074854 00000 n 0000074207 00000 n 0000074360 00000 n 0000074607 00000 n 0000085740 00000 n 0000079827 00000 n 0000082711 00000 n 0000082866 00000 n 0000083005 00000 n 0000083158 00000 n 0000083313 00000 n 0000083468 00000 n 0000083623 00000 n 0000083778 00000 n 0000083931 00000 n 0000084085 00000 n 0000084241 00000 n 0000084396 00000 n 0000084550 00000 n 0000084704 00000 n 0000084859 00000 n 0000085015 00000 n 0000085169 00000 n 0000085325 00000 n 0000085463 00000 n 0000085599 00000 n 0000085795 00000 n 0000079515 00000 n 0000078505 00000 n 0000838116 00000 n 0000080950 00000 n 0000082621 00000 n 0000081079 00000 n 0000082560 00000 n 0000081240 00000 n 0000082490 00000 n 0000081395 00000 n 0000082428 00000 n 0000081556 00000 n 0000082366 00000 n 0000081719 00000 n 0000081872 00000 n 0000082119 00000 n 0000093613 00000 n 0000087282 00000 n 0000090584 00000 n 0000090739 00000 n 0000090878 00000 n 0000091031 00000 n 0000091186 00000 n 0000091341 00000 n 0000091496 00000 n 0000091651 00000 n 0000091804 00000 n 0000091958 00000 n 0000092114 00000 n 0000092269 00000 n 0000092423 00000 n 0000092577 00000 n 0000092732 00000 n 0000092888 00000 n 0000093042 00000 n 0000093198 00000 n 0000093336 00000 n 0000093472 00000 n 0000093668 00000 n 0000086970 00000 n 0000086022 00000 n 0000088578 00000 n 0000090433 00000 n 0000088707 00000 n 0000090372 00000 n 0000089052 00000 n 0000090302 00000 n 0000089207 00000 n 0000090240 00000 n 0000089368 00000 n 0000090178 00000 n 0000089531 00000 n 0000089684 00000 n 0000089931 00000 n 0000101440 00000 n 0000095144 00000 n 0000098411 00000 n 0000098566 00000 n 0000098705 00000 n 0000098858 00000 n 0000099013 00000 n 0000099168 00000 n 0000099323 00000 n 0000099478 00000 n 0000099631 00000 n 0000099785 00000 n 0000099941 00000 n 0000100096 00000 n 0000100250 00000 n 0000100404 00000 n 0000100559 00000 n 0000100715 00000 n 0000100869 00000 n 0000101025 00000 n 0000101163 00000 n 0000101299 00000 n 0000101495 00000 n 0000094832 00000 n 0000093883 00000 n 0000096536 00000 n 0000098267 00000 n 0000096665 00000 n 0000098206 00000 n 0000096850 00000 n 0000098128 00000 n 0000097005 00000 n 0000098066 00000 n 0000097194 00000 n 0000098004 00000 n 0000097357 00000 n 0000097510 00000 n 0000097757 00000 n 0000109213 00000 n 0000102967 00000 n 0000106184 00000 n 0000106339 00000 n 0000106478 00000 n 0000106631 00000 n 0000106786 00000 n 0000106941 00000 n 0000107096 00000 n 0000107251 00000 n 0000107404 00000 n 0000107558 00000 n 0000107714 00000 n 0000107869 00000 n 0000108023 00000 n 0000108177 00000 n 0000108332 00000 n 0000108488 00000 n 0000108642 00000 n 0000108798 00000 n 0000108936 00000 n 0000109072 00000 n 0000109268 00000 n 0000102655 00000 n 0000101710 00000 n 0000104309 00000 n 0000106040 00000 n 0000104438 00000 n 0000105979 00000 n 0000104623 00000 n 0000105901 00000 n 0000104778 00000 n 0000105839 00000 n 0000104967 00000 n 0000105777 00000 n 0000105130 00000 n 0000105283 00000 n 0000105530 00000 n 0000119277 00000 n 0000110941 00000 n 0000113441 00000 n 0000116248 00000 n 0000116403 00000 n 0000116542 00000 n 0000116695 00000 n 0000116850 00000 n 0000117005 00000 n 0000117160 00000 n 0000117315 00000 n 0000117468 00000 n 0000117622 00000 n 0000117778 00000 n 0000117933 00000 n 0000118087 00000 n 0000118241 00000 n 0000118396 00000 n 0000118552 00000 n 0000118706 00000 n 0000118862 00000 n 0000119000 00000 n 0000119136 00000 n 0000119332 00000 n 0000110629 00000 n 0000109471 00000 n 0000837590 00000 n 0000111810 00000 n 0000113380 00000 n 0000111939 00000 n 0000113277 00000 n 0000112094 00000 n 0000113217 00000 n 0000112351 00000 n 0000113155 00000 n 0000112508 00000 n 0000112661 00000 n 0000112908 00000 n 0000114458 00000 n 0000116133 00000 n 0000114587 00000 n 0000116072 00000 n 0000114760 00000 n 0000116002 00000 n 0000114915 00000 n 0000115942 00000 n 0000115076 00000 n 0000115880 00000 n 0000115233 00000 n 0000115386 00000 n 0000115633 00000 n 0000124067 00000 n 0000128484 00000 n 0000121038 00000 n 0000121193 00000 n 0000121332 00000 n 0000121485 00000 n 0000121640 00000 n 0000121795 00000 n 0000121950 00000 n 0000122105 00000 n 0000122258 00000 n 0000122412 00000 n 0000122568 00000 n 0000122723 00000 n 0000122877 00000 n 0000123031 00000 n 0000123186 00000 n 0000123342 00000 n 0000123496 00000 n 0000123652 00000 n 0000123790 00000 n 0000123926 00000 n 0000124122 00000 n 0000120726 00000 n 0000119573 00000 n 0000125455 00000 n 0000125610 00000 n 0000125749 00000 n 0000125902 00000 n 0000126057 00000 n 0000126212 00000 n 0000126367 00000 n 0000126522 00000 n 0000126675 00000 n 0000126829 00000 n 0000126985 00000 n 0000127140 00000 n 0000127294 00000 n 0000127448 00000 n 0000127603 00000 n 0000127759 00000 n 0000127913 00000 n 0000128069 00000 n 0000128207 00000 n 0000128343 00000 n 0000128539 00000 n 0000125143 00000 n 0000124363 00000 n 0000838234 00000 n 0000133308 00000 n 0000130279 00000 n 0000130434 00000 n 0000130573 00000 n 0000130726 00000 n 0000130881 00000 n 0000131036 00000 n 0000131191 00000 n 0000131346 00000 n 0000131499 00000 n 0000131653 00000 n 0000131809 00000 n 0000131964 00000 n 0000132118 00000 n 0000132272 00000 n 0000132427 00000 n 0000132583 00000 n 0000132737 00000 n 0000132893 00000 n 0000133031 00000 n 0000133167 00000 n 0000133363 00000 n 0000129967 00000 n 0000128690 00000 n 0000835409 00000 n 0000141538 00000 n 0000134627 00000 n 0000143173 00000 n 0000151491 00000 n 0000138509 00000 n 0000138664 00000 n 0000138803 00000 n 0000138956 00000 n 0000139111 00000 n 0000139266 00000 n 0000139421 00000 n 0000139576 00000 n 0000139729 00000 n 0000139883 00000 n 0000140039 00000 n 0000140194 00000 n 0000140348 00000 n 0000140502 00000 n 0000140657 00000 n 0000140813 00000 n 0000140967 00000 n 0000141123 00000 n 0000141261 00000 n 0000141397 00000 n 0000141593 00000 n 0000134315 00000 n 0000133511 00000 n 0000136037 00000 n 0000138438 00000 n 0000136166 00000 n 0000138325 00000 n 0000136333 00000 n 0000138259 00000 n 0000136898 00000 n 0000659402 00000 n 0000138131 00000 n 0000137067 00000 n 0000137637 00000 n 0000137884 00000 n 0000659370 00000 n 0000150080 00000 n 0000158690 00000 n 0000163403 00000 n 0000147051 00000 n 0000147206 00000 n 0000147345 00000 n 0000147498 00000 n 0000147653 00000 n 0000147808 00000 n 0000147963 00000 n 0000148118 00000 n 0000148271 00000 n 0000148425 00000 n 0000148581 00000 n 0000148736 00000 n 0000148890 00000 n 0000149044 00000 n 0000149199 00000 n 0000149355 00000 n 0000149509 00000 n 0000149665 00000 n 0000149803 00000 n 0000149939 00000 n 0000150135 00000 n 0000142861 00000 n 0000141745 00000 n 0000835987 00000 n 0000144603 00000 n 0000146900 00000 n 0000144732 00000 n 0000146833 00000 n 0000145077 00000 n 0000146709 00000 n 0000145238 00000 n 0000146647 00000 n 0000145775 00000 n 0000146585 00000 n 0000145938 00000 n 0000146091 00000 n 0000146338 00000 n 0000155661 00000 n 0000155816 00000 n 0000155955 00000 n 0000156108 00000 n 0000156263 00000 n 0000156418 00000 n 0000156573 00000 n 0000156728 00000 n 0000156881 00000 n 0000157035 00000 n 0000157191 00000 n 0000157346 00000 n 0000157500 00000 n 0000157654 00000 n 0000157809 00000 n 0000157965 00000 n 0000158119 00000 n 0000158275 00000 n 0000158413 00000 n 0000158549 00000 n 0000158745 00000 n 0000151179 00000 n 0000150374 00000 n 0000153189 00000 n 0000155590 00000 n 0000153318 00000 n 0000155477 00000 n 0000153485 00000 n 0000155411 00000 n 0000154050 00000 n 0000155283 00000 n 0000154219 00000 n 0000154789 00000 n 0000155036 00000 n 0000160374 00000 n 0000160529 00000 n 0000160668 00000 n 0000160821 00000 n 0000160976 00000 n 0000161131 00000 n 0000161286 00000 n 0000161441 00000 n 0000161594 00000 n 0000161748 00000 n 0000161904 00000 n 0000162059 00000 n 0000162213 00000 n 0000162367 00000 n 0000162522 00000 n 0000162678 00000 n 0000162832 00000 n 0000162988 00000 n 0000163126 00000 n 0000163262 00000 n 0000163458 00000 n 0000160062 00000 n 0000158897 00000 n 0000168111 00000 n 0000173159 00000 n 0000165082 00000 n 0000165237 00000 n 0000165376 00000 n 0000165529 00000 n 0000165684 00000 n 0000165839 00000 n 0000165994 00000 n 0000166149 00000 n 0000166302 00000 n 0000166456 00000 n 0000166612 00000 n 0000166767 00000 n 0000166921 00000 n 0000167075 00000 n 0000167230 00000 n 0000167386 00000 n 0000167540 00000 n 0000167696 00000 n 0000167834 00000 n 0000167970 00000 n 0000168166 00000 n 0000164770 00000 n 0000163606 00000 n 0000838352 00000 n 0000169955 00000 n 0000170111 00000 n 0000170252 00000 n 0000170408 00000 n 0000170563 00000 n 0000170719 00000 n 0000170875 00000 n 0000171031 00000 n 0000171185 00000 n 0000171340 00000 n 0000171497 00000 n 0000171654 00000 n 0000171809 00000 n 0000171964 00000 n 0000172121 00000 n 0000172278 00000 n 0000172433 00000 n 0000172590 00000 n 0000172729 00000 n 0000172866 00000 n 0000173007 00000 n 0000173271 00000 n 0000169635 00000 n 0000168314 00000 n 0000173215 00000 n 0000177805 00000 n 0000174776 00000 n 0000174931 00000 n 0000175070 00000 n 0000175223 00000 n 0000175378 00000 n 0000175533 00000 n 0000175688 00000 n 0000175843 00000 n 0000175996 00000 n 0000176150 00000 n 0000176306 00000 n 0000176461 00000 n 0000176615 00000 n 0000176769 00000 n 0000176924 00000 n 0000177080 00000 n 0000177234 00000 n 0000177390 00000 n 0000177528 00000 n 0000177664 00000 n 0000177860 00000 n 0000174464 00000 n 0000173481 00000 n 0000185174 00000 n 0000179113 00000 n 0000182145 00000 n 0000182300 00000 n 0000182439 00000 n 0000182592 00000 n 0000182747 00000 n 0000182902 00000 n 0000183057 00000 n 0000183212 00000 n 0000183365 00000 n 0000183519 00000 n 0000183675 00000 n 0000183830 00000 n 0000183984 00000 n 0000184138 00000 n 0000184293 00000 n 0000184449 00000 n 0000184603 00000 n 0000184759 00000 n 0000184897 00000 n 0000185033 00000 n 0000185229 00000 n 0000178801 00000 n 0000177995 00000 n 0000180286 00000 n 0000182001 00000 n 0000180415 00000 n 0000181855 00000 n 0000180600 00000 n 0000181790 00000 n 0000181125 00000 n 0000181296 00000 n 0000181543 00000 n 0000192404 00000 n 0000186467 00000 n 0000189375 00000 n 0000189530 00000 n 0000189669 00000 n 0000189822 00000 n 0000189977 00000 n 0000190132 00000 n 0000190287 00000 n 0000190442 00000 n 0000190595 00000 n 0000190749 00000 n 0000190905 00000 n 0000191060 00000 n 0000191214 00000 n 0000191368 00000 n 0000191523 00000 n 0000191679 00000 n 0000191833 00000 n 0000191989 00000 n 0000192127 00000 n 0000192263 00000 n 0000192459 00000 n 0000186155 00000 n 0000185381 00000 n 0000187516 00000 n 0000189231 00000 n 0000187645 00000 n 0000189085 00000 n 0000187830 00000 n 0000189020 00000 n 0000188355 00000 n 0000188526 00000 n 0000188773 00000 n 0000200285 00000 n 0000193731 00000 n 0000197250 00000 n 0000197405 00000 n 0000197544 00000 n 0000197697 00000 n 0000197852 00000 n 0000198007 00000 n 0000198162 00000 n 0000198317 00000 n 0000198470 00000 n 0000198624 00000 n 0000198780 00000 n 0000198935 00000 n 0000199089 00000 n 0000199243 00000 n 0000199398 00000 n 0000199555 00000 n 0000199710 00000 n 0000199867 00000 n 0000200006 00000 n 0000200143 00000 n 0000200341 00000 n 0000193410 00000 n 0000192611 00000 n 0000195447 00000 n 0000197127 00000 n 0000195577 00000 n 0000197052 00000 n 0000196128 00000 n 0000813714 00000 n 0000196988 00000 n 0000196333 00000 n 0000196492 00000 n 0000196740 00000 n 0000813682 00000 n 0000207072 00000 n 0000201783 00000 n 0000204023 00000 n 0000204179 00000 n 0000204319 00000 n 0000204473 00000 n 0000204629 00000 n 0000204785 00000 n 0000204941 00000 n 0000205097 00000 n 0000205251 00000 n 0000205406 00000 n 0000205563 00000 n 0000205719 00000 n 0000205874 00000 n 0000206029 00000 n 0000206185 00000 n 0000206342 00000 n 0000206497 00000 n 0000206654 00000 n 0000206793 00000 n 0000206930 00000 n 0000207129 00000 n 0000201447 00000 n 0000200494 00000 n 0000838471 00000 n 0000202777 00000 n 0000203920 00000 n 0000202907 00000 n 0000203424 00000 n 0000203672 00000 n 0000213758 00000 n 0000208508 00000 n 0000210709 00000 n 0000210865 00000 n 0000211005 00000 n 0000211159 00000 n 0000211315 00000 n 0000211471 00000 n 0000211627 00000 n 0000211783 00000 n 0000211937 00000 n 0000212092 00000 n 0000212249 00000 n 0000212405 00000 n 0000212560 00000 n 0000212715 00000 n 0000212871 00000 n 0000213028 00000 n 0000213183 00000 n 0000213340 00000 n 0000213479 00000 n 0000213616 00000 n 0000213815 00000 n 0000208172 00000 n 0000207295 00000 n 0000209224 00000 n 0000210570 00000 n 0000209354 00000 n 0000210074 00000 n 0000210322 00000 n 0000218493 00000 n 0000215444 00000 n 0000215600 00000 n 0000215740 00000 n 0000215894 00000 n 0000216050 00000 n 0000216206 00000 n 0000216362 00000 n 0000216518 00000 n 0000216672 00000 n 0000216827 00000 n 0000216984 00000 n 0000217140 00000 n 0000217295 00000 n 0000217450 00000 n 0000217606 00000 n 0000217763 00000 n 0000217918 00000 n 0000218075 00000 n 0000218214 00000 n 0000218351 00000 n 0000218550 00000 n 0000215108 00000 n 0000213981 00000 n 0000223590 00000 n 0000220365 00000 n 0000220522 00000 n 0000220664 00000 n 0000220821 00000 n 0000220977 00000 n 0000221134 00000 n 0000221291 00000 n 0000221448 00000 n 0000221603 00000 n 0000221759 00000 n 0000221917 00000 n 0000222075 00000 n 0000222231 00000 n 0000222387 00000 n 0000222545 00000 n 0000222703 00000 n 0000222859 00000 n 0000223017 00000 n 0000223157 00000 n 0000223295 00000 n 0000223437 00000 n 0000223706 00000 n 0000220020 00000 n 0000218698 00000 n 0000223648 00000 n 0000228104 00000 n 0000225055 00000 n 0000225211 00000 n 0000225351 00000 n 0000225505 00000 n 0000225661 00000 n 0000225817 00000 n 0000225973 00000 n 0000226129 00000 n 0000226283 00000 n 0000226438 00000 n 0000226595 00000 n 0000226751 00000 n 0000226906 00000 n 0000227061 00000 n 0000227217 00000 n 0000227374 00000 n 0000227529 00000 n 0000227686 00000 n 0000227825 00000 n 0000227962 00000 n 0000228161 00000 n 0000224719 00000 n 0000223917 00000 n 0000232477 00000 n 0000229428 00000 n 0000229584 00000 n 0000229724 00000 n 0000229878 00000 n 0000230034 00000 n 0000230190 00000 n 0000230346 00000 n 0000230502 00000 n 0000230656 00000 n 0000230811 00000 n 0000230968 00000 n 0000231124 00000 n 0000231279 00000 n 0000231434 00000 n 0000231590 00000 n 0000231747 00000 n 0000231902 00000 n 0000232059 00000 n 0000232198 00000 n 0000232335 00000 n 0000232534 00000 n 0000229092 00000 n 0000228285 00000 n 0000240166 00000 n 0000233818 00000 n 0000237117 00000 n 0000237273 00000 n 0000237413 00000 n 0000237567 00000 n 0000237723 00000 n 0000237879 00000 n 0000238035 00000 n 0000238191 00000 n 0000238345 00000 n 0000238500 00000 n 0000238657 00000 n 0000238813 00000 n 0000238968 00000 n 0000239123 00000 n 0000239279 00000 n 0000239436 00000 n 0000239591 00000 n 0000239748 00000 n 0000239887 00000 n 0000240024 00000 n 0000240223 00000 n 0000233482 00000 n 0000232687 00000 n 0000838596 00000 n 0000235323 00000 n 0000237003 00000 n 0000235453 00000 n 0000236928 00000 n 0000236004 00000 n 0000236864 00000 n 0000236209 00000 n 0000236368 00000 n 0000236616 00000 n 0000246923 00000 n 0000241674 00000 n 0000243874 00000 n 0000244030 00000 n 0000244170 00000 n 0000244324 00000 n 0000244480 00000 n 0000244636 00000 n 0000244792 00000 n 0000244948 00000 n 0000245102 00000 n 0000245257 00000 n 0000245414 00000 n 0000245570 00000 n 0000245725 00000 n 0000245880 00000 n 0000246036 00000 n 0000246193 00000 n 0000246348 00000 n 0000246505 00000 n 0000246644 00000 n 0000246781 00000 n 0000246980 00000 n 0000241338 00000 n 0000240377 00000 n 0000242613 00000 n 0000243771 00000 n 0000242743 00000 n 0000243275 00000 n 0000243523 00000 n 0000251595 00000 n 0000248546 00000 n 0000248702 00000 n 0000248842 00000 n 0000248996 00000 n 0000249152 00000 n 0000249308 00000 n 0000249464 00000 n 0000249620 00000 n 0000249774 00000 n 0000249929 00000 n 0000250086 00000 n 0000250242 00000 n 0000250397 00000 n 0000250552 00000 n 0000250708 00000 n 0000250865 00000 n 0000251020 00000 n 0000251177 00000 n 0000251316 00000 n 0000251453 00000 n 0000251652 00000 n 0000248210 00000 n 0000247146 00000 n 0000255967 00000 n 0000252918 00000 n 0000253074 00000 n 0000253214 00000 n 0000253368 00000 n 0000253524 00000 n 0000253680 00000 n 0000253836 00000 n 0000253992 00000 n 0000254146 00000 n 0000254301 00000 n 0000254458 00000 n 0000254614 00000 n 0000254769 00000 n 0000254924 00000 n 0000255080 00000 n 0000255237 00000 n 0000255392 00000 n 0000255549 00000 n 0000255688 00000 n 0000255825 00000 n 0000256024 00000 n 0000252582 00000 n 0000251788 00000 n 0000260844 00000 n 0000257795 00000 n 0000257951 00000 n 0000258091 00000 n 0000258245 00000 n 0000258401 00000 n 0000258557 00000 n 0000258713 00000 n 0000258869 00000 n 0000259023 00000 n 0000259178 00000 n 0000259335 00000 n 0000259491 00000 n 0000259646 00000 n 0000259801 00000 n 0000259957 00000 n 0000260114 00000 n 0000260269 00000 n 0000260426 00000 n 0000260565 00000 n 0000260702 00000 n 0000260901 00000 n 0000257459 00000 n 0000256178 00000 n 0000837737 00000 n 0000835553 00000 n 0000265778 00000 n 0000270760 00000 n 0000262729 00000 n 0000262885 00000 n 0000263025 00000 n 0000263179 00000 n 0000263335 00000 n 0000263491 00000 n 0000263647 00000 n 0000263803 00000 n 0000263957 00000 n 0000264112 00000 n 0000264269 00000 n 0000264425 00000 n 0000264580 00000 n 0000264735 00000 n 0000264891 00000 n 0000265048 00000 n 0000265203 00000 n 0000265360 00000 n 0000265499 00000 n 0000265636 00000 n 0000265835 00000 n 0000262393 00000 n 0000261115 00000 n 0000267711 00000 n 0000267867 00000 n 0000268007 00000 n 0000268161 00000 n 0000268317 00000 n 0000268473 00000 n 0000268629 00000 n 0000268785 00000 n 0000268939 00000 n 0000269094 00000 n 0000269251 00000 n 0000269407 00000 n 0000269562 00000 n 0000269717 00000 n 0000269873 00000 n 0000270030 00000 n 0000270185 00000 n 0000270342 00000 n 0000270481 00000 n 0000270618 00000 n 0000270817 00000 n 0000267375 00000 n 0000266049 00000 n 0000838721 00000 n 0000275538 00000 n 0000272489 00000 n 0000272645 00000 n 0000272785 00000 n 0000272939 00000 n 0000273095 00000 n 0000273251 00000 n 0000273407 00000 n 0000273563 00000 n 0000273717 00000 n 0000273872 00000 n 0000274029 00000 n 0000274185 00000 n 0000274340 00000 n 0000274495 00000 n 0000274651 00000 n 0000274808 00000 n 0000274963 00000 n 0000275120 00000 n 0000275259 00000 n 0000275396 00000 n 0000275595 00000 n 0000272153 00000 n 0000271031 00000 n 0000280253 00000 n 0000284966 00000 n 0000290642 00000 n 0000277204 00000 n 0000277360 00000 n 0000277500 00000 n 0000277654 00000 n 0000277810 00000 n 0000277966 00000 n 0000278122 00000 n 0000278278 00000 n 0000278432 00000 n 0000278587 00000 n 0000278744 00000 n 0000278900 00000 n 0000279055 00000 n 0000279210 00000 n 0000279366 00000 n 0000279523 00000 n 0000279678 00000 n 0000279835 00000 n 0000279974 00000 n 0000280111 00000 n 0000280310 00000 n 0000276868 00000 n 0000275743 00000 n 0000281917 00000 n 0000282073 00000 n 0000282213 00000 n 0000282367 00000 n 0000282523 00000 n 0000282679 00000 n 0000282835 00000 n 0000282991 00000 n 0000283145 00000 n 0000283300 00000 n 0000283457 00000 n 0000283613 00000 n 0000283768 00000 n 0000283923 00000 n 0000284079 00000 n 0000284236 00000 n 0000284391 00000 n 0000284548 00000 n 0000284687 00000 n 0000284824 00000 n 0000285023 00000 n 0000281581 00000 n 0000280458 00000 n 0000286692 00000 n 0000287593 00000 n 0000287749 00000 n 0000287889 00000 n 0000288043 00000 n 0000288199 00000 n 0000288355 00000 n 0000288511 00000 n 0000288667 00000 n 0000288821 00000 n 0000288976 00000 n 0000289133 00000 n 0000289289 00000 n 0000289444 00000 n 0000289599 00000 n 0000289755 00000 n 0000289912 00000 n 0000290067 00000 n 0000290224 00000 n 0000290363 00000 n 0000290500 00000 n 0000290699 00000 n 0000286356 00000 n 0000285171 00000 n 0000286897 00000 n 0000295452 00000 n 0000305058 00000 n 0000310187 00000 n 0000292403 00000 n 0000292559 00000 n 0000292699 00000 n 0000292853 00000 n 0000293009 00000 n 0000293165 00000 n 0000293321 00000 n 0000293477 00000 n 0000293631 00000 n 0000293786 00000 n 0000293943 00000 n 0000294099 00000 n 0000294254 00000 n 0000294409 00000 n 0000294565 00000 n 0000294722 00000 n 0000294877 00000 n 0000295034 00000 n 0000295173 00000 n 0000295310 00000 n 0000295509 00000 n 0000292067 00000 n 0000290879 00000 n 0000300257 00000 n 0000297208 00000 n 0000297364 00000 n 0000297504 00000 n 0000297658 00000 n 0000297814 00000 n 0000297970 00000 n 0000298126 00000 n 0000298282 00000 n 0000298436 00000 n 0000298591 00000 n 0000298748 00000 n 0000298904 00000 n 0000299059 00000 n 0000299214 00000 n 0000299370 00000 n 0000299527 00000 n 0000299682 00000 n 0000299839 00000 n 0000299978 00000 n 0000300115 00000 n 0000300314 00000 n 0000296872 00000 n 0000295689 00000 n 0000838846 00000 n 0000302009 00000 n 0000302165 00000 n 0000302305 00000 n 0000302459 00000 n 0000302615 00000 n 0000302771 00000 n 0000302927 00000 n 0000303083 00000 n 0000303237 00000 n 0000303392 00000 n 0000303549 00000 n 0000303705 00000 n 0000303860 00000 n 0000304015 00000 n 0000304171 00000 n 0000304328 00000 n 0000304483 00000 n 0000304640 00000 n 0000304779 00000 n 0000304916 00000 n 0000305115 00000 n 0000301673 00000 n 0000300494 00000 n 0000306962 00000 n 0000307119 00000 n 0000307261 00000 n 0000307418 00000 n 0000307574 00000 n 0000307731 00000 n 0000307888 00000 n 0000308045 00000 n 0000308200 00000 n 0000308356 00000 n 0000308514 00000 n 0000308672 00000 n 0000308828 00000 n 0000308984 00000 n 0000309142 00000 n 0000309300 00000 n 0000309456 00000 n 0000309614 00000 n 0000309754 00000 n 0000309892 00000 n 0000310034 00000 n 0000310303 00000 n 0000306617 00000 n 0000305295 00000 n 0000310245 00000 n 0000314704 00000 n 0000311655 00000 n 0000311811 00000 n 0000311951 00000 n 0000312105 00000 n 0000312261 00000 n 0000312417 00000 n 0000312573 00000 n 0000312729 00000 n 0000312883 00000 n 0000313038 00000 n 0000313195 00000 n 0000313351 00000 n 0000313506 00000 n 0000313661 00000 n 0000313817 00000 n 0000313974 00000 n 0000314129 00000 n 0000314286 00000 n 0000314425 00000 n 0000314562 00000 n 0000314761 00000 n 0000311319 00000 n 0000310514 00000 n 0000319252 00000 n 0000316203 00000 n 0000316359 00000 n 0000316499 00000 n 0000316653 00000 n 0000316809 00000 n 0000316965 00000 n 0000317121 00000 n 0000317277 00000 n 0000317431 00000 n 0000317586 00000 n 0000317743 00000 n 0000317899 00000 n 0000318054 00000 n 0000318209 00000 n 0000318365 00000 n 0000318522 00000 n 0000318677 00000 n 0000318834 00000 n 0000318973 00000 n 0000319110 00000 n 0000319309 00000 n 0000315867 00000 n 0000314885 00000 n 0000836712 00000 n 0000323955 00000 n 0000328568 00000 n 0000332901 00000 n 0000320906 00000 n 0000321062 00000 n 0000321202 00000 n 0000321356 00000 n 0000321512 00000 n 0000321668 00000 n 0000321824 00000 n 0000321980 00000 n 0000322134 00000 n 0000322289 00000 n 0000322446 00000 n 0000322602 00000 n 0000322757 00000 n 0000322912 00000 n 0000323068 00000 n 0000323225 00000 n 0000323380 00000 n 0000323537 00000 n 0000323676 00000 n 0000323813 00000 n 0000324012 00000 n 0000320570 00000 n 0000319447 00000 n 0000325519 00000 n 0000325675 00000 n 0000325815 00000 n 0000325969 00000 n 0000326125 00000 n 0000326281 00000 n 0000326437 00000 n 0000326593 00000 n 0000326747 00000 n 0000326902 00000 n 0000327059 00000 n 0000327215 00000 n 0000327370 00000 n 0000327525 00000 n 0000327681 00000 n 0000327838 00000 n 0000327993 00000 n 0000328150 00000 n 0000328289 00000 n 0000328426 00000 n 0000328625 00000 n 0000325183 00000 n 0000324150 00000 n 0000838971 00000 n 0000329852 00000 n 0000330008 00000 n 0000330148 00000 n 0000330302 00000 n 0000330458 00000 n 0000330614 00000 n 0000330770 00000 n 0000330926 00000 n 0000331080 00000 n 0000331235 00000 n 0000331392 00000 n 0000331548 00000 n 0000331703 00000 n 0000331858 00000 n 0000332014 00000 n 0000332171 00000 n 0000332326 00000 n 0000332483 00000 n 0000332622 00000 n 0000332759 00000 n 0000332958 00000 n 0000329516 00000 n 0000328787 00000 n 0000337476 00000 n 0000334427 00000 n 0000334583 00000 n 0000334723 00000 n 0000334877 00000 n 0000335033 00000 n 0000335189 00000 n 0000335345 00000 n 0000335501 00000 n 0000335655 00000 n 0000335810 00000 n 0000335967 00000 n 0000336123 00000 n 0000336278 00000 n 0000336433 00000 n 0000336589 00000 n 0000336746 00000 n 0000336901 00000 n 0000337058 00000 n 0000337197 00000 n 0000337334 00000 n 0000337533 00000 n 0000334091 00000 n 0000333082 00000 n 0000342091 00000 n 0000346703 00000 n 0000351095 00000 n 0000339042 00000 n 0000339198 00000 n 0000339338 00000 n 0000339492 00000 n 0000339648 00000 n 0000339804 00000 n 0000339960 00000 n 0000340116 00000 n 0000340270 00000 n 0000340425 00000 n 0000340582 00000 n 0000340738 00000 n 0000340893 00000 n 0000341048 00000 n 0000341204 00000 n 0000341361 00000 n 0000341516 00000 n 0000341673 00000 n 0000341812 00000 n 0000341949 00000 n 0000342148 00000 n 0000338706 00000 n 0000337693 00000 n 0000343654 00000 n 0000343810 00000 n 0000343950 00000 n 0000344104 00000 n 0000344260 00000 n 0000344416 00000 n 0000344572 00000 n 0000344728 00000 n 0000344882 00000 n 0000345037 00000 n 0000345194 00000 n 0000345350 00000 n 0000345505 00000 n 0000345660 00000 n 0000345816 00000 n 0000345973 00000 n 0000346128 00000 n 0000346285 00000 n 0000346424 00000 n 0000346561 00000 n 0000346760 00000 n 0000343318 00000 n 0000342308 00000 n 0000348046 00000 n 0000348202 00000 n 0000348342 00000 n 0000348496 00000 n 0000348652 00000 n 0000348808 00000 n 0000348964 00000 n 0000349120 00000 n 0000349274 00000 n 0000349429 00000 n 0000349586 00000 n 0000349742 00000 n 0000349897 00000 n 0000350052 00000 n 0000350208 00000 n 0000350365 00000 n 0000350520 00000 n 0000350677 00000 n 0000350816 00000 n 0000350953 00000 n 0000351152 00000 n 0000347710 00000 n 0000346920 00000 n 0000355765 00000 n 0000352716 00000 n 0000352872 00000 n 0000353012 00000 n 0000353166 00000 n 0000353322 00000 n 0000353478 00000 n 0000353634 00000 n 0000353790 00000 n 0000353944 00000 n 0000354099 00000 n 0000354256 00000 n 0000354412 00000 n 0000354567 00000 n 0000354722 00000 n 0000354878 00000 n 0000355035 00000 n 0000355190 00000 n 0000355347 00000 n 0000355486 00000 n 0000355623 00000 n 0000355822 00000 n 0000352380 00000 n 0000351306 00000 n 0000839096 00000 n 0000360471 00000 n 0000365297 00000 n 0000357422 00000 n 0000357578 00000 n 0000357718 00000 n 0000357872 00000 n 0000358028 00000 n 0000358184 00000 n 0000358340 00000 n 0000358496 00000 n 0000358650 00000 n 0000358805 00000 n 0000358962 00000 n 0000359118 00000 n 0000359273 00000 n 0000359428 00000 n 0000359584 00000 n 0000359741 00000 n 0000359896 00000 n 0000360053 00000 n 0000360192 00000 n 0000360329 00000 n 0000360528 00000 n 0000357086 00000 n 0000356011 00000 n 0000362248 00000 n 0000362404 00000 n 0000362544 00000 n 0000362698 00000 n 0000362854 00000 n 0000363010 00000 n 0000363166 00000 n 0000363322 00000 n 0000363476 00000 n 0000363631 00000 n 0000363788 00000 n 0000363944 00000 n 0000364099 00000 n 0000364254 00000 n 0000364410 00000 n 0000364567 00000 n 0000364722 00000 n 0000364879 00000 n 0000365018 00000 n 0000365155 00000 n 0000365354 00000 n 0000361912 00000 n 0000360717 00000 n 0000370095 00000 n 0000374958 00000 n 0000367046 00000 n 0000367202 00000 n 0000367342 00000 n 0000367496 00000 n 0000367652 00000 n 0000367808 00000 n 0000367964 00000 n 0000368120 00000 n 0000368274 00000 n 0000368429 00000 n 0000368586 00000 n 0000368742 00000 n 0000368897 00000 n 0000369052 00000 n 0000369208 00000 n 0000369365 00000 n 0000369520 00000 n 0000369677 00000 n 0000369816 00000 n 0000369953 00000 n 0000370152 00000 n 0000366710 00000 n 0000365519 00000 n 0000371909 00000 n 0000372065 00000 n 0000372205 00000 n 0000372359 00000 n 0000372515 00000 n 0000372671 00000 n 0000372827 00000 n 0000372983 00000 n 0000373137 00000 n 0000373292 00000 n 0000373449 00000 n 0000373605 00000 n 0000373760 00000 n 0000373915 00000 n 0000374071 00000 n 0000374228 00000 n 0000374383 00000 n 0000374540 00000 n 0000374679 00000 n 0000374816 00000 n 0000375015 00000 n 0000371573 00000 n 0000370317 00000 n 0000379811 00000 n 0000384709 00000 n 0000376762 00000 n 0000376918 00000 n 0000377058 00000 n 0000377212 00000 n 0000377368 00000 n 0000377524 00000 n 0000377680 00000 n 0000377836 00000 n 0000377990 00000 n 0000378145 00000 n 0000378302 00000 n 0000378458 00000 n 0000378613 00000 n 0000378768 00000 n 0000378924 00000 n 0000379081 00000 n 0000379236 00000 n 0000379393 00000 n 0000379532 00000 n 0000379669 00000 n 0000379868 00000 n 0000376426 00000 n 0000375175 00000 n 0000381660 00000 n 0000381816 00000 n 0000381956 00000 n 0000382110 00000 n 0000382266 00000 n 0000382422 00000 n 0000382578 00000 n 0000382734 00000 n 0000382888 00000 n 0000383043 00000 n 0000383200 00000 n 0000383356 00000 n 0000383511 00000 n 0000383666 00000 n 0000383822 00000 n 0000383979 00000 n 0000384134 00000 n 0000384291 00000 n 0000384430 00000 n 0000384567 00000 n 0000384766 00000 n 0000381324 00000 n 0000380028 00000 n 0000839221 00000 n 0000389578 00000 n 0000394234 00000 n 0000386529 00000 n 0000386685 00000 n 0000386825 00000 n 0000386979 00000 n 0000387135 00000 n 0000387291 00000 n 0000387447 00000 n 0000387603 00000 n 0000387757 00000 n 0000387912 00000 n 0000388069 00000 n 0000388225 00000 n 0000388380 00000 n 0000388535 00000 n 0000388691 00000 n 0000388848 00000 n 0000389003 00000 n 0000389160 00000 n 0000389299 00000 n 0000389436 00000 n 0000389635 00000 n 0000386193 00000 n 0000384902 00000 n 0000391185 00000 n 0000391341 00000 n 0000391481 00000 n 0000391635 00000 n 0000391791 00000 n 0000391947 00000 n 0000392103 00000 n 0000392259 00000 n 0000392413 00000 n 0000392568 00000 n 0000392725 00000 n 0000392881 00000 n 0000393036 00000 n 0000393191 00000 n 0000393347 00000 n 0000393504 00000 n 0000393659 00000 n 0000393816 00000 n 0000393955 00000 n 0000394092 00000 n 0000394291 00000 n 0000390849 00000 n 0000389771 00000 n 0000399319 00000 n 0000396094 00000 n 0000396251 00000 n 0000396393 00000 n 0000396550 00000 n 0000396706 00000 n 0000396863 00000 n 0000397020 00000 n 0000397177 00000 n 0000397332 00000 n 0000397488 00000 n 0000397646 00000 n 0000397804 00000 n 0000397960 00000 n 0000398116 00000 n 0000398274 00000 n 0000398432 00000 n 0000398588 00000 n 0000398746 00000 n 0000398886 00000 n 0000399024 00000 n 0000399166 00000 n 0000399435 00000 n 0000395749 00000 n 0000394427 00000 n 0000399377 00000 n 0000403829 00000 n 0000400780 00000 n 0000400936 00000 n 0000401076 00000 n 0000401230 00000 n 0000401386 00000 n 0000401542 00000 n 0000401698 00000 n 0000401854 00000 n 0000402008 00000 n 0000402163 00000 n 0000402320 00000 n 0000402476 00000 n 0000402631 00000 n 0000402786 00000 n 0000402942 00000 n 0000403099 00000 n 0000403254 00000 n 0000403411 00000 n 0000403550 00000 n 0000403687 00000 n 0000403886 00000 n 0000400444 00000 n 0000399646 00000 n 0000408472 00000 n 0000405423 00000 n 0000405579 00000 n 0000405719 00000 n 0000405873 00000 n 0000406029 00000 n 0000406185 00000 n 0000406341 00000 n 0000406497 00000 n 0000406651 00000 n 0000406806 00000 n 0000406963 00000 n 0000407119 00000 n 0000407274 00000 n 0000407429 00000 n 0000407585 00000 n 0000407742 00000 n 0000407897 00000 n 0000408054 00000 n 0000408193 00000 n 0000408330 00000 n 0000408529 00000 n 0000405087 00000 n 0000404010 00000 n 0000416444 00000 n 0000409931 00000 n 0000417971 00000 n 0000426240 00000 n 0000434565 00000 n 0000442866 00000 n 0000413395 00000 n 0000413551 00000 n 0000413691 00000 n 0000413845 00000 n 0000414001 00000 n 0000414157 00000 n 0000414313 00000 n 0000414469 00000 n 0000414623 00000 n 0000414778 00000 n 0000414935 00000 n 0000415091 00000 n 0000415246 00000 n 0000415401 00000 n 0000415557 00000 n 0000415714 00000 n 0000415869 00000 n 0000416026 00000 n 0000416165 00000 n 0000416302 00000 n 0000416501 00000 n 0000409595 00000 n 0000408679 00000 n 0000839346 00000 n 0000410972 00000 n 0000413307 00000 n 0000411102 00000 n 0000413245 00000 n 0000411263 00000 n 0000413147 00000 n 0000411420 00000 n 0000413084 00000 n 0000411627 00000 n 0000413006 00000 n 0000411792 00000 n 0000412911 00000 n 0000411953 00000 n 0000412415 00000 n 0000412663 00000 n 0000424713 00000 n 0000448676 00000 n 0000453479 00000 n 0000421664 00000 n 0000421820 00000 n 0000421960 00000 n 0000422114 00000 n 0000422270 00000 n 0000422426 00000 n 0000422582 00000 n 0000422738 00000 n 0000422892 00000 n 0000423047 00000 n 0000423204 00000 n 0000423360 00000 n 0000423515 00000 n 0000423670 00000 n 0000423826 00000 n 0000423983 00000 n 0000424138 00000 n 0000424295 00000 n 0000424434 00000 n 0000424571 00000 n 0000424770 00000 n 0000417635 00000 n 0000416718 00000 n 0000419091 00000 n 0000421540 00000 n 0000419221 00000 n 0000421478 00000 n 0000419491 00000 n 0000421375 00000 n 0000419648 00000 n 0000421312 00000 n 0000419855 00000 n 0000421234 00000 n 0000420020 00000 n 0000421139 00000 n 0000420181 00000 n 0000420643 00000 n 0000420891 00000 n 0000433038 00000 n 0000429989 00000 n 0000430145 00000 n 0000430285 00000 n 0000430439 00000 n 0000430595 00000 n 0000430751 00000 n 0000430907 00000 n 0000431063 00000 n 0000431217 00000 n 0000431372 00000 n 0000431529 00000 n 0000431685 00000 n 0000431840 00000 n 0000431995 00000 n 0000432151 00000 n 0000432308 00000 n 0000432463 00000 n 0000432620 00000 n 0000432759 00000 n 0000432896 00000 n 0000433095 00000 n 0000425904 00000 n 0000424987 00000 n 0000427372 00000 n 0000429837 00000 n 0000427502 00000 n 0000429775 00000 n 0000427849 00000 n 0000429696 00000 n 0000428006 00000 n 0000429633 00000 n 0000428197 00000 n 0000429570 00000 n 0000428362 00000 n 0000429475 00000 n 0000428517 00000 n 0000428979 00000 n 0000429227 00000 n 0000441199 00000 n 0000438150 00000 n 0000438306 00000 n 0000438446 00000 n 0000438600 00000 n 0000438756 00000 n 0000438912 00000 n 0000439068 00000 n 0000439224 00000 n 0000439378 00000 n 0000439533 00000 n 0000439690 00000 n 0000439846 00000 n 0000440001 00000 n 0000440156 00000 n 0000440312 00000 n 0000440469 00000 n 0000440624 00000 n 0000440781 00000 n 0000440920 00000 n 0000441057 00000 n 0000441256 00000 n 0000434229 00000 n 0000433312 00000 n 0000435736 00000 n 0000438005 00000 n 0000435866 00000 n 0000437943 00000 n 0000436053 00000 n 0000437872 00000 n 0000436210 00000 n 0000437809 00000 n 0000436373 00000 n 0000437746 00000 n 0000436538 00000 n 0000437651 00000 n 0000436693 00000 n 0000437155 00000 n 0000437403 00000 n 0000445627 00000 n 0000445783 00000 n 0000445923 00000 n 0000446077 00000 n 0000446233 00000 n 0000446389 00000 n 0000446545 00000 n 0000446701 00000 n 0000446855 00000 n 0000447010 00000 n 0000447167 00000 n 0000447323 00000 n 0000447478 00000 n 0000447633 00000 n 0000447789 00000 n 0000447946 00000 n 0000448101 00000 n 0000448258 00000 n 0000448397 00000 n 0000448534 00000 n 0000448733 00000 n 0000442530 00000 n 0000441473 00000 n 0000443770 00000 n 0000445482 00000 n 0000443900 00000 n 0000445420 00000 n 0000444087 00000 n 0000445349 00000 n 0000444244 00000 n 0000445286 00000 n 0000444407 00000 n 0000445223 00000 n 0000444572 00000 n 0000444727 00000 n 0000444975 00000 n 0000450430 00000 n 0000450586 00000 n 0000450726 00000 n 0000450880 00000 n 0000451036 00000 n 0000451192 00000 n 0000451348 00000 n 0000451504 00000 n 0000451658 00000 n 0000451813 00000 n 0000451970 00000 n 0000452126 00000 n 0000452281 00000 n 0000452436 00000 n 0000452592 00000 n 0000452749 00000 n 0000452904 00000 n 0000453061 00000 n 0000453200 00000 n 0000453337 00000 n 0000453536 00000 n 0000450094 00000 n 0000448962 00000 n 0000458252 00000 n 0000463499 00000 n 0000455203 00000 n 0000455359 00000 n 0000455499 00000 n 0000455653 00000 n 0000455809 00000 n 0000455965 00000 n 0000456121 00000 n 0000456277 00000 n 0000456431 00000 n 0000456586 00000 n 0000456743 00000 n 0000456899 00000 n 0000457054 00000 n 0000457209 00000 n 0000457365 00000 n 0000457522 00000 n 0000457677 00000 n 0000457834 00000 n 0000457973 00000 n 0000458110 00000 n 0000458309 00000 n 0000454867 00000 n 0000453738 00000 n 0000839471 00000 n 0000460450 00000 n 0000460606 00000 n 0000460746 00000 n 0000460900 00000 n 0000461056 00000 n 0000461212 00000 n 0000461368 00000 n 0000461524 00000 n 0000461678 00000 n 0000461833 00000 n 0000461990 00000 n 0000462146 00000 n 0000462301 00000 n 0000462456 00000 n 0000462612 00000 n 0000462769 00000 n 0000462924 00000 n 0000463081 00000 n 0000463220 00000 n 0000463357 00000 n 0000463556 00000 n 0000460114 00000 n 0000458511 00000 n 0000468749 00000 n 0000494992 00000 n 0000500208 00000 n 0000465700 00000 n 0000465856 00000 n 0000465996 00000 n 0000466150 00000 n 0000466306 00000 n 0000466462 00000 n 0000466618 00000 n 0000466774 00000 n 0000466928 00000 n 0000467083 00000 n 0000467240 00000 n 0000467396 00000 n 0000467551 00000 n 0000467706 00000 n 0000467862 00000 n 0000468019 00000 n 0000468174 00000 n 0000468331 00000 n 0000468470 00000 n 0000468607 00000 n 0000468806 00000 n 0000465364 00000 n 0000463756 00000 n 0000474000 00000 n 0000470951 00000 n 0000471107 00000 n 0000471247 00000 n 0000471401 00000 n 0000471557 00000 n 0000471713 00000 n 0000471869 00000 n 0000472025 00000 n 0000472179 00000 n 0000472334 00000 n 0000472491 00000 n 0000472647 00000 n 0000472802 00000 n 0000472957 00000 n 0000473113 00000 n 0000473270 00000 n 0000473425 00000 n 0000473582 00000 n 0000473721 00000 n 0000473858 00000 n 0000474057 00000 n 0000470615 00000 n 0000469006 00000 n 0000479250 00000 n 0000476201 00000 n 0000476357 00000 n 0000476497 00000 n 0000476651 00000 n 0000476807 00000 n 0000476963 00000 n 0000477119 00000 n 0000477275 00000 n 0000477429 00000 n 0000477584 00000 n 0000477741 00000 n 0000477897 00000 n 0000478052 00000 n 0000478207 00000 n 0000478363 00000 n 0000478520 00000 n 0000478675 00000 n 0000478832 00000 n 0000478971 00000 n 0000479108 00000 n 0000479307 00000 n 0000475865 00000 n 0000474257 00000 n 0000484499 00000 n 0000481450 00000 n 0000481606 00000 n 0000481746 00000 n 0000481900 00000 n 0000482056 00000 n 0000482212 00000 n 0000482368 00000 n 0000482524 00000 n 0000482678 00000 n 0000482833 00000 n 0000482990 00000 n 0000483146 00000 n 0000483301 00000 n 0000483456 00000 n 0000483612 00000 n 0000483769 00000 n 0000483924 00000 n 0000484081 00000 n 0000484220 00000 n 0000484357 00000 n 0000484556 00000 n 0000481114 00000 n 0000479507 00000 n 0000489747 00000 n 0000486698 00000 n 0000486854 00000 n 0000486994 00000 n 0000487148 00000 n 0000487304 00000 n 0000487460 00000 n 0000487616 00000 n 0000487772 00000 n 0000487926 00000 n 0000488081 00000 n 0000488238 00000 n 0000488394 00000 n 0000488549 00000 n 0000488704 00000 n 0000488860 00000 n 0000489017 00000 n 0000489172 00000 n 0000489329 00000 n 0000489468 00000 n 0000489605 00000 n 0000489804 00000 n 0000486362 00000 n 0000484756 00000 n 0000839596 00000 n 0000491943 00000 n 0000492099 00000 n 0000492239 00000 n 0000492393 00000 n 0000492549 00000 n 0000492705 00000 n 0000492861 00000 n 0000493017 00000 n 0000493171 00000 n 0000493326 00000 n 0000493483 00000 n 0000493639 00000 n 0000493794 00000 n 0000493949 00000 n 0000494105 00000 n 0000494262 00000 n 0000494417 00000 n 0000494574 00000 n 0000494713 00000 n 0000494850 00000 n 0000495049 00000 n 0000491607 00000 n 0000490004 00000 n 0000497159 00000 n 0000497315 00000 n 0000497455 00000 n 0000497609 00000 n 0000497765 00000 n 0000497921 00000 n 0000498077 00000 n 0000498233 00000 n 0000498387 00000 n 0000498542 00000 n 0000498699 00000 n 0000498855 00000 n 0000499010 00000 n 0000499165 00000 n 0000499321 00000 n 0000499478 00000 n 0000499633 00000 n 0000499790 00000 n 0000499929 00000 n 0000500066 00000 n 0000500265 00000 n 0000496823 00000 n 0000495249 00000 n 0000837004 00000 n 0000505432 00000 n 0000510654 00000 n 0000516234 00000 n 0000502383 00000 n 0000502539 00000 n 0000502679 00000 n 0000502833 00000 n 0000502989 00000 n 0000503145 00000 n 0000503301 00000 n 0000503457 00000 n 0000503611 00000 n 0000503766 00000 n 0000503923 00000 n 0000504079 00000 n 0000504234 00000 n 0000504389 00000 n 0000504545 00000 n 0000504702 00000 n 0000504857 00000 n 0000505014 00000 n 0000505153 00000 n 0000505290 00000 n 0000505489 00000 n 0000502047 00000 n 0000500469 00000 n 0000507605 00000 n 0000507761 00000 n 0000507901 00000 n 0000508055 00000 n 0000508211 00000 n 0000508367 00000 n 0000508523 00000 n 0000508679 00000 n 0000508833 00000 n 0000508988 00000 n 0000509145 00000 n 0000509301 00000 n 0000509456 00000 n 0000509611 00000 n 0000509767 00000 n 0000509924 00000 n 0000510079 00000 n 0000510236 00000 n 0000510375 00000 n 0000510512 00000 n 0000510711 00000 n 0000507269 00000 n 0000505693 00000 n 0000513185 00000 n 0000513341 00000 n 0000513481 00000 n 0000513635 00000 n 0000513791 00000 n 0000513947 00000 n 0000514103 00000 n 0000514259 00000 n 0000514413 00000 n 0000514568 00000 n 0000514725 00000 n 0000514881 00000 n 0000515036 00000 n 0000515191 00000 n 0000515347 00000 n 0000515504 00000 n 0000515659 00000 n 0000515816 00000 n 0000515955 00000 n 0000516092 00000 n 0000516291 00000 n 0000512849 00000 n 0000510915 00000 n 0000835843 00000 n 0000521844 00000 n 0000538675 00000 n 0000546273 00000 n 0000518795 00000 n 0000518951 00000 n 0000519091 00000 n 0000519245 00000 n 0000519401 00000 n 0000519557 00000 n 0000519713 00000 n 0000519869 00000 n 0000520023 00000 n 0000520178 00000 n 0000520335 00000 n 0000520491 00000 n 0000520646 00000 n 0000520801 00000 n 0000520957 00000 n 0000521114 00000 n 0000521269 00000 n 0000521426 00000 n 0000521565 00000 n 0000521702 00000 n 0000521901 00000 n 0000518459 00000 n 0000516522 00000 n 0000839721 00000 n 0000527457 00000 n 0000524408 00000 n 0000524564 00000 n 0000524704 00000 n 0000524858 00000 n 0000525014 00000 n 0000525170 00000 n 0000525326 00000 n 0000525482 00000 n 0000525636 00000 n 0000525791 00000 n 0000525948 00000 n 0000526104 00000 n 0000526259 00000 n 0000526414 00000 n 0000526570 00000 n 0000526727 00000 n 0000526882 00000 n 0000527039 00000 n 0000527178 00000 n 0000527315 00000 n 0000527514 00000 n 0000524072 00000 n 0000522132 00000 n 0000533067 00000 n 0000530018 00000 n 0000530174 00000 n 0000530314 00000 n 0000530468 00000 n 0000530624 00000 n 0000530780 00000 n 0000530936 00000 n 0000531092 00000 n 0000531246 00000 n 0000531401 00000 n 0000531558 00000 n 0000531714 00000 n 0000531869 00000 n 0000532024 00000 n 0000532180 00000 n 0000532337 00000 n 0000532492 00000 n 0000532649 00000 n 0000532788 00000 n 0000532925 00000 n 0000533124 00000 n 0000529682 00000 n 0000527745 00000 n 0000535626 00000 n 0000535782 00000 n 0000535922 00000 n 0000536076 00000 n 0000536232 00000 n 0000536388 00000 n 0000536544 00000 n 0000536700 00000 n 0000536854 00000 n 0000537009 00000 n 0000537166 00000 n 0000537322 00000 n 0000537477 00000 n 0000537632 00000 n 0000537788 00000 n 0000537945 00000 n 0000538100 00000 n 0000538257 00000 n 0000538396 00000 n 0000538533 00000 n 0000538732 00000 n 0000535290 00000 n 0000533355 00000 n 0000540083 00000 n 0000543224 00000 n 0000543380 00000 n 0000543520 00000 n 0000543674 00000 n 0000543830 00000 n 0000543986 00000 n 0000544142 00000 n 0000544298 00000 n 0000544452 00000 n 0000544607 00000 n 0000544764 00000 n 0000544920 00000 n 0000545075 00000 n 0000545230 00000 n 0000545386 00000 n 0000545543 00000 n 0000545698 00000 n 0000545855 00000 n 0000545994 00000 n 0000546131 00000 n 0000546330 00000 n 0000539747 00000 n 0000538963 00000 n 0000541846 00000 n 0000543088 00000 n 0000541976 00000 n 0000542592 00000 n 0000542840 00000 n 0000553897 00000 n 0000547620 00000 n 0000550848 00000 n 0000551004 00000 n 0000551144 00000 n 0000551298 00000 n 0000551454 00000 n 0000551610 00000 n 0000551766 00000 n 0000551922 00000 n 0000552076 00000 n 0000552231 00000 n 0000552388 00000 n 0000552544 00000 n 0000552699 00000 n 0000552854 00000 n 0000553010 00000 n 0000553167 00000 n 0000553322 00000 n 0000553479 00000 n 0000553618 00000 n 0000553755 00000 n 0000553954 00000 n 0000547284 00000 n 0000546484 00000 n 0000548964 00000 n 0000550766 00000 n 0000549094 00000 n 0000550586 00000 n 0000549275 00000 n 0000550525 00000 n 0000549870 00000 n 0000550029 00000 n 0000550277 00000 n 0000560749 00000 n 0000555243 00000 n 0000557700 00000 n 0000557856 00000 n 0000557996 00000 n 0000558150 00000 n 0000558306 00000 n 0000558462 00000 n 0000558618 00000 n 0000558774 00000 n 0000558928 00000 n 0000559083 00000 n 0000559240 00000 n 0000559396 00000 n 0000559551 00000 n 0000559706 00000 n 0000559862 00000 n 0000560019 00000 n 0000560174 00000 n 0000560331 00000 n 0000560470 00000 n 0000560607 00000 n 0000560806 00000 n 0000554907 00000 n 0000554108 00000 n 0000839846 00000 n 0000556313 00000 n 0000557561 00000 n 0000556443 00000 n 0000557065 00000 n 0000557313 00000 n 0000567576 00000 n 0000562296 00000 n 0000564527 00000 n 0000564683 00000 n 0000564823 00000 n 0000564977 00000 n 0000565133 00000 n 0000565289 00000 n 0000565445 00000 n 0000565601 00000 n 0000565755 00000 n 0000565910 00000 n 0000566067 00000 n 0000566223 00000 n 0000566378 00000 n 0000566533 00000 n 0000566689 00000 n 0000566846 00000 n 0000567001 00000 n 0000567158 00000 n 0000567297 00000 n 0000567434 00000 n 0000567633 00000 n 0000561960 00000 n 0000560960 00000 n 0000563212 00000 n 0000564406 00000 n 0000563342 00000 n 0000563910 00000 n 0000564158 00000 n 0000572707 00000 n 0000569480 00000 n 0000569637 00000 n 0000569779 00000 n 0000569937 00000 n 0000570093 00000 n 0000570250 00000 n 0000570407 00000 n 0000570565 00000 n 0000570720 00000 n 0000570876 00000 n 0000571034 00000 n 0000571192 00000 n 0000571348 00000 n 0000571504 00000 n 0000571662 00000 n 0000571820 00000 n 0000571976 00000 n 0000572134 00000 n 0000572274 00000 n 0000572412 00000 n 0000572554 00000 n 0000572823 00000 n 0000569135 00000 n 0000567813 00000 n 0000572765 00000 n 0000577205 00000 n 0000574152 00000 n 0000574308 00000 n 0000574448 00000 n 0000574603 00000 n 0000574759 00000 n 0000574916 00000 n 0000575073 00000 n 0000575230 00000 n 0000575384 00000 n 0000575539 00000 n 0000575696 00000 n 0000575852 00000 n 0000576007 00000 n 0000576162 00000 n 0000576318 00000 n 0000576475 00000 n 0000576630 00000 n 0000576787 00000 n 0000576926 00000 n 0000577063 00000 n 0000577262 00000 n 0000573816 00000 n 0000573034 00000 n 0000582028 00000 n 0000578973 00000 n 0000579130 00000 n 0000579270 00000 n 0000579425 00000 n 0000579582 00000 n 0000579739 00000 n 0000579896 00000 n 0000580053 00000 n 0000580207 00000 n 0000580362 00000 n 0000580519 00000 n 0000580675 00000 n 0000580830 00000 n 0000580985 00000 n 0000581141 00000 n 0000581298 00000 n 0000581453 00000 n 0000581610 00000 n 0000581749 00000 n 0000581886 00000 n 0000582085 00000 n 0000578637 00000 n 0000577386 00000 n 0000586867 00000 n 0000596543 00000 n 0000603713 00000 n 0000583812 00000 n 0000583969 00000 n 0000584109 00000 n 0000584264 00000 n 0000584421 00000 n 0000584578 00000 n 0000584735 00000 n 0000584892 00000 n 0000585046 00000 n 0000585201 00000 n 0000585358 00000 n 0000585514 00000 n 0000585669 00000 n 0000585824 00000 n 0000585980 00000 n 0000586137 00000 n 0000586292 00000 n 0000586449 00000 n 0000586588 00000 n 0000586725 00000 n 0000586924 00000 n 0000583476 00000 n 0000582221 00000 n 0000591708 00000 n 0000588653 00000 n 0000588810 00000 n 0000588950 00000 n 0000589105 00000 n 0000589262 00000 n 0000589419 00000 n 0000589576 00000 n 0000589733 00000 n 0000589887 00000 n 0000590042 00000 n 0000590199 00000 n 0000590355 00000 n 0000590510 00000 n 0000590665 00000 n 0000590821 00000 n 0000590978 00000 n 0000591133 00000 n 0000591290 00000 n 0000591429 00000 n 0000591566 00000 n 0000591765 00000 n 0000588317 00000 n 0000587060 00000 n 0000839971 00000 n 0000593488 00000 n 0000593645 00000 n 0000593785 00000 n 0000593940 00000 n 0000594097 00000 n 0000594254 00000 n 0000594411 00000 n 0000594568 00000 n 0000594722 00000 n 0000594877 00000 n 0000595034 00000 n 0000595190 00000 n 0000595345 00000 n 0000595500 00000 n 0000595656 00000 n 0000595813 00000 n 0000595968 00000 n 0000596125 00000 n 0000596264 00000 n 0000596401 00000 n 0000596600 00000 n 0000593152 00000 n 0000591901 00000 n 0000598066 00000 n 0000600658 00000 n 0000600815 00000 n 0000600955 00000 n 0000601110 00000 n 0000601267 00000 n 0000601424 00000 n 0000601581 00000 n 0000601738 00000 n 0000601892 00000 n 0000602047 00000 n 0000602204 00000 n 0000602360 00000 n 0000602515 00000 n 0000602670 00000 n 0000602826 00000 n 0000602983 00000 n 0000603138 00000 n 0000603295 00000 n 0000603434 00000 n 0000603571 00000 n 0000603770 00000 n 0000597730 00000 n 0000596736 00000 n 0000598960 00000 n 0000600569 00000 n 0000599090 00000 n 0000600505 00000 n 0000599617 00000 n 0000600441 00000 n 0000599786 00000 n 0000599945 00000 n 0000600193 00000 n 0000608803 00000 n 0000605748 00000 n 0000605905 00000 n 0000606045 00000 n 0000606200 00000 n 0000606357 00000 n 0000606514 00000 n 0000606671 00000 n 0000606828 00000 n 0000606982 00000 n 0000607137 00000 n 0000607294 00000 n 0000607450 00000 n 0000607605 00000 n 0000607760 00000 n 0000607916 00000 n 0000608073 00000 n 0000608228 00000 n 0000608385 00000 n 0000608524 00000 n 0000608661 00000 n 0000608860 00000 n 0000605412 00000 n 0000603975 00000 n 0000613849 00000 n 0000618651 00000 n 0000610794 00000 n 0000610951 00000 n 0000611091 00000 n 0000611246 00000 n 0000611403 00000 n 0000611560 00000 n 0000611717 00000 n 0000611874 00000 n 0000612028 00000 n 0000612183 00000 n 0000612340 00000 n 0000612496 00000 n 0000612651 00000 n 0000612806 00000 n 0000612962 00000 n 0000613119 00000 n 0000613274 00000 n 0000613431 00000 n 0000613570 00000 n 0000613707 00000 n 0000613906 00000 n 0000610458 00000 n 0000609025 00000 n 0000615596 00000 n 0000615753 00000 n 0000615893 00000 n 0000616048 00000 n 0000616205 00000 n 0000616362 00000 n 0000616519 00000 n 0000616676 00000 n 0000616830 00000 n 0000616985 00000 n 0000617142 00000 n 0000617298 00000 n 0000617453 00000 n 0000617608 00000 n 0000617764 00000 n 0000617921 00000 n 0000618076 00000 n 0000618233 00000 n 0000618372 00000 n 0000618509 00000 n 0000618708 00000 n 0000615260 00000 n 0000614071 00000 n 0000623429 00000 n 0000628204 00000 n 0000632762 00000 n 0000620374 00000 n 0000620531 00000 n 0000620671 00000 n 0000620826 00000 n 0000620983 00000 n 0000621140 00000 n 0000621297 00000 n 0000621454 00000 n 0000621608 00000 n 0000621763 00000 n 0000621920 00000 n 0000622076 00000 n 0000622231 00000 n 0000622386 00000 n 0000622542 00000 n 0000622699 00000 n 0000622854 00000 n 0000623011 00000 n 0000623150 00000 n 0000623287 00000 n 0000623486 00000 n 0000620038 00000 n 0000618844 00000 n 0000840096 00000 n 0000625149 00000 n 0000625306 00000 n 0000625446 00000 n 0000625601 00000 n 0000625758 00000 n 0000625915 00000 n 0000626072 00000 n 0000626229 00000 n 0000626383 00000 n 0000626538 00000 n 0000626695 00000 n 0000626851 00000 n 0000627006 00000 n 0000627161 00000 n 0000627317 00000 n 0000627474 00000 n 0000627629 00000 n 0000627786 00000 n 0000627925 00000 n 0000628062 00000 n 0000628261 00000 n 0000624813 00000 n 0000623622 00000 n 0000629526 00000 n 0000629707 00000 n 0000629864 00000 n 0000630004 00000 n 0000630159 00000 n 0000630316 00000 n 0000630473 00000 n 0000630630 00000 n 0000630787 00000 n 0000630941 00000 n 0000631096 00000 n 0000631253 00000 n 0000631409 00000 n 0000631564 00000 n 0000631719 00000 n 0000631875 00000 n 0000632032 00000 n 0000632187 00000 n 0000632344 00000 n 0000632483 00000 n 0000632620 00000 n 0000632819 00000 n 0000629181 00000 n 0000628397 00000 n 0000837149 00000 n 0000637055 00000 n 0000634000 00000 n 0000634157 00000 n 0000634297 00000 n 0000634452 00000 n 0000634609 00000 n 0000634766 00000 n 0000634923 00000 n 0000635080 00000 n 0000635234 00000 n 0000635389 00000 n 0000635546 00000 n 0000635702 00000 n 0000635857 00000 n 0000636012 00000 n 0000636168 00000 n 0000636325 00000 n 0000636480 00000 n 0000636637 00000 n 0000636776 00000 n 0000636913 00000 n 0000637112 00000 n 0000633664 00000 n 0000632957 00000 n 0000638903 00000 n 0000639061 00000 n 0000639203 00000 n 0000639361 00000 n 0000639518 00000 n 0000639676 00000 n 0000639834 00000 n 0000639992 00000 n 0000640147 00000 n 0000640303 00000 n 0000640461 00000 n 0000640619 00000 n 0000640775 00000 n 0000640931 00000 n 0000641089 00000 n 0000641247 00000 n 0000641403 00000 n 0000641561 00000 n 0000641701 00000 n 0000641839 00000 n 0000641981 00000 n 0000642248 00000 n 0000638558 00000 n 0000637236 00000 n 0000642190 00000 n 0000642552 00000 n 0000642860 00000 n 0000642884 00000 n 0000642910 00000 n 0000643528 00000 n 0000643822 00000 n 0000643848 00000 n 0000643938 00000 n 0000643965 00000 n 0000644031 00000 n 0000644055 00000 n 0000644674 00000 n 0000644706 00000 n 0000645079 00000 n 0000645431 00000 n 0000646089 00000 n 0000646746 00000 n 0000647426 00000 n 0000659654 00000 n 0000667921 00000 n 0000677750 00000 n 0000684760 00000 n 0000684988 00000 n 0000703231 00000 n 0000710660 00000 n 0000710884 00000 n 0000718879 00000 n 0000734814 00000 n 0000744762 00000 n 0000745069 00000 n 0000753066 00000 n 0000753319 00000 n 0000769667 00000 n 0000770117 00000 n 0000782065 00000 n 0000782424 00000 n 0000789528 00000 n 0000789755 00000 n 0000797247 00000 n 0000797476 00000 n 0000806686 00000 n 0000813928 00000 n 0000820934 00000 n 0000821161 00000 n 0000832356 00000 n 0000832623 00000 n 0000835190 00000 n 0000840212 00000 n 0000840332 00000 n 0000840458 00000 n 0000840584 00000 n 0000840664 00000 n 0000840756 00000 n 0000840965 00000 n 0000841190 00000 n 0000841411 00000 n 0000841622 00000 n 0000841831 00000 n 0000842042 00000 n 0000842254 00000 n 0000842471 00000 n 0000842685 00000 n 0000842899 00000 n 0000843116 00000 n 0000843331 00000 n 0000843548 00000 n 0000843763 00000 n 0000843980 00000 n 0000844195 00000 n 0000844412 00000 n 0000844627 00000 n 0000844844 00000 n 0000845014 00000 n 0000845115 00000 n 0000845238 00000 n 0000845364 00000 n 0000845490 00000 n 0000845584 00000 n 0000845684 00000 n 0000845724 00000 n 0000846710 00000 n trailer << /Size 3269 /Root 3267 0 R /Info 3268 0 R /ID [<6D32036A328BA7F03B3CFA6A86BFF7D8> <6D32036A328BA7F03B3CFA6A86BFF7D8>] >> startxref 847118 %%EOF mathicgb-master/examples/000077500000000000000000000000001311555162500157475ustar00rootroot00000000000000mathicgb-master/examples/cyclic4.ideal000077500000000000000000000001071311555162500203020ustar00rootroot00000000000000101 4 1 1 1 1 1 4 a+b+c+d ab+bc+cd+da abc+bcd+cda+dab abcd-1 mathicgb-master/examples/cyclic5.ideal000077500000000000000000000001561311555162500203070ustar00rootroot00000000000000101 5 1 1 1 1 1 1 5 a+b+c+d+e ab+bc+cd+de+ea abc+bcd+cde+dea+eab abcd+bcde+cdea+deab+eabc abcde-1 mathicgb-master/examples/cyclic7.ideal000077500000000000000000000003501311555162500203050ustar00rootroot00000000000000101 7 1 1 1 1 1 1 1 1 7 a+b+c+d+e+f+g ab+bc+cd+de+ef+fg+ga abc+bcd+cde+def+efg+fga+gab abcd+bcde+cdef+defg+efga+fgab+gabc abcde+bcdef+cdefg+defga+efgab+fgabc+gabcd abcdef+bcdefg+cdefga+defgab+efgabc+fgabcd+gabcde abcdefg-1 mathicgb-master/examples/hilbertkunz1.ideal000066400000000000000000000001541311555162500213710ustar00rootroot000000000000005 4 1 1 1 1 1 5 a3-2a2b-ab2-2b3+abc-2b2c+2ac2-2bc2-c3+2abd-2b2d-acd-2bcd-2c2d+ad2+cd2-d3 a125 b125 c125 d25 mathicgb-master/examples/hkatsura-101/000077500000000000000000000000001311555162500200705ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura11-101/000077500000000000000000000000001311555162500223535ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura11-101/hkatsura11-101-trimmed.ideal000066400000000000000000000032771311555162500273060ustar00rootroot00000000000000101 12 1 1 1 1 1 1 1 1 1 1 1 1 1 11 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k-l fg-23g2+eh-46fh-40gh-41h2+di-46ei-40fi+19gi+30hi+47i2+cj-46dj-40ej+19fj+30gj-7hj+9ij+39j2+bk-46ck-40dk+19ek+30fk-7gk+9hk-23ik-2jk+36k2+12bl+48cl+7dl-10el-3fl+28gl-18hl-40il-38jl-12kl f2+2eg+47g2+2dh-7fh-19gh-18h2+2ci-7ei-19fi-36gi+43hi+8i2+2bj-7dj-19ej-36fj+43gj+16hj-16ij+24j2-4bk-11ck-23dk-40ek+39fk+12gk-20hk+44ik+2jk+26k2-24bl+5cl-14dl+20el+6fl+45gl+36hl-21il-25jl+25kl ef+dg+ch+bi-2bj-2cj-2dj-2ej-2fj-2gj-2hj-2ij-2j2+bk-2jk-50jl e2+2df+2cg+2bh-4bi-4ci-4di-4ei-4fi-4gi-4hi-4i2+2bj-4ij+2ck-4ik+il de+cf+bg-2bh-2ch-2dh-2eh-2fh-2gh-2h2+bi-2hi+cj-2hj+dk-2hk-50hl d2+2ce+2bf-4bg-4cg-4dg-4eg+5g2+2bh+4eh+18fh+38gh+38h2+2ci+4di+18ei+42fi-29gi+19hi-14i2+4cj+20dj+42ej-25fj+15gj-28hj+36ij-46j2+4bk+18ck+42dk-23ek+19fk-32gk+36hk+9ik-8jk+43k2+48bl-10cl+28dl-40el-12fl+12gl+29hl+42il+50jl-48kl cd+be-2bf-2cf-2df+bg+2dg+4eg+48g2+3ch+4dh+2eh-7fh-17gh-17h2+2bi+4ci+3di-5ei-19fi-34gi+45hi+9i2-2cj-9dj-20ej-40fj+41gj+14hj-18ij+21j2-4bk-13ck-25dk-42ek+36fk+10gk-22hk+42ik-4jk+23k2-24bl+5cl-14dl+20el-44fl+45gl+36hl-21il-24jl+26kl c2+2bd-4be-4ce+2bf+4cf+8df+4bg+10cg+4dg-4eg-4ch-6dh-12eh-8fh-8gh-8h2-8bi-16ci-16di-18ei-16fi-16gi-24hi-16i2-4cj-8dj-12ej-6fj-8gj-16hj-24ij-8j2+4bk+8ck+4dk-4ek+2gk-8hk-16ik-8jk+el+2hl+4il+2jl bc-2bd+3be+4ce-cf-6df-4bg-8cg-5dg+5g2+2ch+2dh+9eh+18fh+38gh+38h2+6bi+12ci+12di+26ei+47fi-25gi+23hi-10i2+6cj+20dj+44ej-29fj+12gj-32hj+36ij-50j2+10ck+34dk-29ek+9fk-44gk+25hk+ik-24jk+31k2+48bl-10cl-22dl-40el-11fl+13gl+30hl+42il-49jl-44kl b2+2bd-2ce+2df+4bg+4cg+4dg+2eg+10g2-4eh+14fh-49gh-49h2-4ci-4di+12ei+48fi+5gi-26hi+33i2-4cj+12dj+48ej+3fj-22gj-33hj-24ij-47j2+16ck-49dk+3ek-22fk-27gk-20hk+9ik-43jk+14k2-5bl-19cl-43dl+25el-18fl+30gl-31hl-il+19jl+29kl mathicgb-master/examples/hkatsura-101/hkatsura11-101/hkatsura11-101.ideal000066400000000000000000000006631311555162500256430ustar00rootroot00000000000000101 12 1 1 1 1 1 1 1 1 1 1 1 1 1 11 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k-l a2+2b2+2c2+2d2+2e2+2f2+2g2+2h2+2i2+2j2+2k2-al 2ab+2bc+2cd+2de+2ef+2fg+2gh+2hi+2ij+2jk-bl b2+2ac+2bd+2ce+2df+2eg+2fh+2gi+2hj+2ik-cl 2bc+2ad+2be+2cf+2dg+2eh+2fi+2gj+2hk-dl c2+2bd+2ae+2bf+2cg+2dh+2ei+2fj+2gk-el 2cd+2be+2af+2bg+2ch+2di+2ej+2fk-fl d2+2ce+2bf+2ag+2bh+2ci+2dj+2ek-gl 2de+2cf+2bg+2ah+2bi+2cj+2dk-hl e2+2df+2cg+2bh+2ai+2bj+2ck-il 2ef+2dg+2ch+2bi+2aj+2bk-jl mathicgb-master/examples/hkatsura-101/hkatsura12-101/000077500000000000000000000000001311555162500223545ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura12-101/hkatsura12-101-trimmed.ideal000066400000000000000000000040371311555162500273030ustar00rootroot00000000000000101 13 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l-m g2+2fh-9gh+34h2+2ei-9fi-33gi+31hi+41i2+2dj-9ej-33fj+31gj-19hj+19ij+22j2+2ck-9dk-33ek+31fk-19gk+19hk+44ik-45jk-23k2+2bl-9cl-33dl+31el-19fl+19gl+44hl-45il-46jl+41kl+7l2-22bm+13cm+4dm-49em-45fm+16gm+33hm+6im+36jm+22km-36lm fg+eh-45gh+34h2+di-45fi-33gi+36hi-20i2+cj-45ej-33fj+36gj-40hj+42ij+40j2+bk-45dk-33ek+36fk-40gk+42hk-21ik-27jk+12k2-2bl-47cl-35dl+34el-42fl+40gl-23hl-29il+22jl+29kl-5l2+11bm+44cm-2dm-26em-28fm-8gm+34hm-3im-18jm-11km-32lm f2+2eg+2dh+2ci+2bj-4bk-4ck-4dk-4ek-4fk-4gk-4hk-4ik-4jk-4k2+2bl-4kl+km ef+dg+ch+bi-2bj-2cj-2dj-2ej-2fj-2gj-2hj-2ij-2j2+bk-2jk+cl-2jl-50jm e2+2df+2cg+2bh-4bi-4ci-4di-4ei-4fi-4gi-4hi-4i2+2bj-4ij+2ck-4ik+2dl-4il+im de+cf+bg-2bh-2ch-2dh-2eh-2fh-2gh-2h2+bi-2hi+cj-2hj+dk-2hk+el-2hl-50hm d2+2ce+2bf-4bg-4cg-4dg-4eg+2bh+4eh+8fh-18gh-31h2+2ci+4di+8ei-14fi+35gi-35hi-17i2+4cj+10dj-14ej+39fj-39gj-34hj+42ij+46j2+4bk+8ck-14dk+41ek-35fk-38gk+42hk-9ik+15jk-44k2-22cl+31dl-43el-40fl+30gl-17hl+7il+5jl-23kl+8l2-44bm+26cm+8dm+3em+11fm+33gm-35hm+12im-29jm+44km+31lm cd+be-2bf-2cf-2df+bg+2dg+4eg+3ch+4dh+2eh-2fh+11gh-33h2+2bi+4ci+3di+9fi+35gi-29hi-40i2-2cj-4dj+8ej+29fj-33gj+17hj-21ij-25j2-4bk-8ck+3dk+27ek-38fk+13gk-25hk-50ik+35jk+16k2+9cl+31dl-33el+15fl-20gl-46hl+43il+40jl+50kl-10l2+22bm-13cm-4dm+49em-5fm-16gm-33hm-6im-35jm-20km+37lm c2+2bd-4be-4ce+2bf+4cf+8df+4bg+10cg+4dg-4eg-4ch-6dh-12eh-8fh-8gh-8h2-8bi-16ci-16di-18ei-16fi-16gi-24hi-16i2-4cj-8dj-12ej-6fj-8gj-16hj-24ij-8j2+4bk+8ck+4dk-4ek+2gk-8hk-16ik-8jk+4cl+8dl-6hl-16il-8jl+em+2hm+4im+2jm bc-2bd+3be+4ce-cf-6df-4bg-8cg-5dg+2ch+2dh+9eh+8fh-18gh-31h2+6bi+12ci+12di+16ei-9fi+39gi-31hi-13i2+6cj+10dj-12ej+35fj-42gj-38hj+42ij+42j2-22dk+35ek-45fk-50gk+31hk-17ik-jk+45k2-26cl+21dl-49el-50fl+20gl-29hl-11jl-47kl-4l2-44bm+26cm-42dm+3em+12fm+34gm-34hm+12im-27jm+48km+35lm b2+2bd-2ce+2df+4bg+4cg+4dg+2eg-4eh-6fh+41gh+15h2-4ci-4di-8ei+37fi+32gi-33hi+27i2-4cj-8dj+37ej+30fj-29gj-45hj-12ij+36j2-4ck+41dk+30ek-29fk-39gk-8hk-27ik+3jk+42k2+45cl+38dl-25el-39fl-21hl+7il-15jl+12kl+45l2+13bm-48cm+18dm+10em+28fm-29gm+43hm+40im-38jm+11km-15lm mathicgb-master/examples/hkatsura-101/hkatsura12-101/hkatsura12-101.ideal000066400000000000000000000007761311555162500256520ustar00rootroot00000000000000101 13 1 1 1 1 1 1 1 1 1 1 1 1 1 1 12 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l-m a2+2b2+2c2+2d2+2e2+2f2+2g2+2h2+2i2+2j2+2k2+2l2-am 2ab+2bc+2cd+2de+2ef+2fg+2gh+2hi+2ij+2jk+2kl-bm b2+2ac+2bd+2ce+2df+2eg+2fh+2gi+2hj+2ik+2jl-cm 2bc+2ad+2be+2cf+2dg+2eh+2fi+2gj+2hk+2il-dm c2+2bd+2ae+2bf+2cg+2dh+2ei+2fj+2gk+2hl-em 2cd+2be+2af+2bg+2ch+2di+2ej+2fk+2gl-fm d2+2ce+2bf+2ag+2bh+2ci+2dj+2ek+2fl-gm 2de+2cf+2bg+2ah+2bi+2cj+2dk+2el-hm e2+2df+2cg+2bh+2ai+2bj+2ck+2dl-im 2ef+2dg+2ch+2bi+2aj+2bk+2cl-jm f2+2eg+2dh+2ci+2bj+2ak+2bl-km mathicgb-master/examples/hkatsura-101/hkatsura13-101/000077500000000000000000000000001311555162500223555ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura13-101/hkatsura13-101-trimmed.ideal000066400000000000000000000052251311555162500273050ustar00rootroot00000000000000101 14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 13 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m-n gh-3h2+fi-6gi-21hi-22i2+ej-6fj-21gj-44hj+26ij+44j2+dk-6ek-21fk-44gk+26hk-13ik+41jk-7k2+cl-6dl-21el-44fl+26gl-13hl+41il-14jl+24kl+27l2+bm-6cm-21dm-44em+26fm-13gm+41hm-14im+24jm-47km-25lm+45m2+2bn+8cn+18dn+32en+50fn-29gn-3hn+27in-40jn-2kn+40ln-15mn g2+2fh+7h2+2ei+14gi+44hi+45i2+2dj+14fj+44gj-11hj-50ij+14j2+2ck+14ek+44fk-11gk-50hk+28ik+21jk+15k2+2bl+14dl+44el-11fl-50gl+28hl+21il+30jl-46kl+48l2-4bm+10cm+40dm-15em+47fm+24gm+17hm+26im-50jm-9km+48lm+8m2-4bn-16cn-36dn+37en+fn-43gn+6hn+47in-21jn+4kn+21ln+31mn fg+eh+di+cj+bk-2bl-2cl-2dl-2el-2fl-2gl-2hl-2il-2jl-2kl-2l2+bm-2lm-50ln f2+2eg+2dh+2ci+2bj-4bk-4ck-4dk-4ek-4fk-4gk-4hk-4ik-4jk-4k2+2bl-4kl+2cm-4km+kn ef+dg+ch+bi-2bj-2cj-2dj-2ej-2fj-2gj-2hj-2ij-2j2+bk-2jk+cl-2jl+dm-2jm-50jn e2+2df+2cg+2bh-4bi-4ci-4di-4ei-4fi-4gi-4hi-4i2+2bj-4ij+2ck-4ik+2dl-4il+2em-4im+in de+cf+bg-2bh-2ch-2dh-2eh-2fh-8h2+bi+2fi-12gi-44hi-44i2+cj+2ej-12fj-42gj+11hj-49ij-13j2+3dk-12ek-42fk+13gk+50hk-26ik-19jk-14k2+2cl-12dl-41el+13fl-49gl-28hl-19il-28jl+48kl-47l2+2bm-12cm-42dm+13em-48fm-26gm-21hm-28im+48jm+7km-50lm-11m2+4bn+16cn+36dn-37en-fn+43gn+45hn-47in+21jn-4kn-21ln-30mn d2+2ce+2bf-4bg-4cg-4dg-4eg+2bh+4eh+8fh+16h2+2ci+4di+8ei+4fi+28gi-9hi-9i2+4cj+10dj+4ej+32fj-13gj-18hj+5ij+30j2+4bk+8ck+4dk+34ek-9fk-22gk+5hk-41ik+46jk+32k2-4cl+24dl-17el-24fl-7gl-49hl+38il-45jl+5kl-11l2-8bm+16cm-25dm-34em-11fm+42gm+30hm+48im-3jm-22km-17lm+10m2-8bn-32cn+29dn-27en+2fn+16gn+12hn-7in-42jn+8kn+44ln-37mn cd+be-2bf-2cf-2df+bg+2dg+4eg+3ch+4dh+2eh-2fh+2bi+4ci+3di-2fi-2cj-4dj-3ej-6fj-4gj-4hj-4ij-4j2-4bk-8ck-8dk-8ek-9fk-8gk-8hk-8ik-12jk-8k2-2cl-4dl-4el-6fl-3gl-4hl-4il-8jl-12kl-4l2+2bm+4cm+2dm-2fm+hm-4jm-8km-4lm-50fn+jn+2kn+ln c2+2bd-4be-4ce+2bf+4cf+8df+4bg+10cg+4dg-4eg-4ch-6dh-12eh-8fh-32h2-8bi-16ci-16di-18ei-8fi+37gi+10hi+10i2-4cj-8dj-4ej+47fj+26gj+36hj-18ij+41j2+4bk+8ck+12dk+49ek+34fk-47gk-2hk-19ik+17jk+45k2+12cl-40dl+34el-49fl+6gl-9hl+9il-19jl-10kl+14l2+8bm-48cm+38dm-45em+10fm-3gm+17hm-25im-18jm+28km+2lm-44m2+16bn-37cn+43dn-46en-4fn-30gn-22hn+18in-15jn-16kn+17ln-19mn bc-2bd+3be+4ce-cf-6df-4bg-8cg-5dg+2ch+2dh+9eh+8fh+16h2+6bi+12ci+12di+16ei+9fi+32gi-5hi-5i2+6cj+10dj+6ej+28fj-16gj-22hj+5ij+26j2-4dk+28ek-19fk-34gk-6hk-49ik+30jk+20k2-8cl+14dl-23el-34fl-17gl+40hl+31il+40jl-19kl-23l2-8bm+16cm-31dm-42em-21fm+32gm+20hm+40im-18jm-46km-41lm-2m2-8bn-32cn-21dn-27en+3fn+17gn+13hn-7in-40jn+12kn+48ln-33mn b2+2bd-2ce+2df+4bg+4cg+4dg+2eg-4eh-6fh+37h2-4ci-4di-8ei-4fi-25gi+20hi+20i2-4cj-8dj-4ej-27fj+24gj+42hj+33ij+50j2-4ck-27ek+24fk+48gk+37hk+ik+39jk+26k2+4cl-19dl+28el+48fl+45gl+7hl+43il-47jl+38kl+49l2+8bm-15cm+36dm-45em+49fm+15gm-50hm-41im+42jm-km+30lm+18m2+32bn+28cn-13dn+11en-2fn+49gn-36hn+44in-14jn-8kn-39ln-6mn mathicgb-master/examples/hkatsura-101/hkatsura13-101/hkatsura13-101.ideal000066400000000000000000000011161311555162500256410ustar00rootroot00000000000000101 14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 13 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m-n a2+2b2+2c2+2d2+2e2+2f2+2g2+2h2+2i2+2j2+2k2+2l2+2m2-an 2ab+2bc+2cd+2de+2ef+2fg+2gh+2hi+2ij+2jk+2kl+2lm-bn b2+2ac+2bd+2ce+2df+2eg+2fh+2gi+2hj+2ik+2jl+2km-cn 2bc+2ad+2be+2cf+2dg+2eh+2fi+2gj+2hk+2il+2jm-dn c2+2bd+2ae+2bf+2cg+2dh+2ei+2fj+2gk+2hl+2im-en 2cd+2be+2af+2bg+2ch+2di+2ej+2fk+2gl+2hm-fn d2+2ce+2bf+2ag+2bh+2ci+2dj+2ek+2fl+2gm-gn 2de+2cf+2bg+2ah+2bi+2cj+2dk+2el+2fm-hn e2+2df+2cg+2bh+2ai+2bj+2ck+2dl+2em-in 2ef+2dg+2ch+2bi+2aj+2bk+2cl+2dm-jn f2+2eg+2dh+2ci+2bj+2ak+2bl+2cm-kn 2fg+2eh+2di+2cj+2bk+2al+2bm-ln mathicgb-master/examples/hkatsura-101/hkatsura14-101/000077500000000000000000000000001311555162500223565ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura14-101/hkatsura14-101-trimmed.ideal000066400000000000000000000061531311555162500273100ustar00rootroot00000000000000101 15 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n-o h2+2gi-37hi-8i2+2fj-37gj-16hj-36ij+2j2+2ek-37fk-16gk-36hk+4ik+3jk+31k2+2dl-37el-16fl-36gl+4hl+3il-39jl-21kl-22l2+2cm-37dm-16em-36fm+4gm+3hm-39im-21jm-44km-7lm+45m2+2bn-37cn-16dn-36en+4fn+3gn-39hn-21in-44jn-7kn-11ln+45mn+30n2-15bo+41co-34do-38eo+29fo-35go-28ho+50io-3jo+15ko+3lo-39mo-10no gh+fi-31hi-46i2+ej-31gj+9hj+19ij+50j2+dk-31fk+9gk+19hk-ik+50jk-15k2+cl-31el+9fl+19gl-hl+50il-30jl-39kl-39l2+bm-31dm+9em+19fm-gm+50hm-30im-39jm+23km-46lm-22m2-2bn-33cn+7dn+17en-3fn+48gn-32hn-41in+21jn-48kn-46ln+27mn+34n2-43bo+30co+17do+19eo+36fo-33go+14ho-25io-49jo+43ko+49lo-31mo-45no g2+2fh+2ei+2dj+2ck+2bl-4bm-4cm-4dm-4em-4fm-4gm-4hm-4im-4jm-4km-4lm-4m2+2bn-4mn+mo fg+eh+di+cj+bk-2bl-2cl-2dl-2el-2fl-2gl-2hl-2il-2jl-2kl-2l2+bm-2lm+cn-2ln-50lo f2+2eg+2dh+2ci+2bj-4bk-4ck-4dk-4ek-4fk-4gk-4hk-4ik-4jk-4k2+2bl-4kl+2cm-4km+2dn-4kn+ko ef+dg+ch+bi-2bj-2cj-2dj-2ej-2fj-2gj-2hj-2ij-2j2+bk-2jk+cl-2jl+dm-2jm+en-2jn-50jo e2+2df+2cg+2bh-4bi-4ci-4di-4ei-4fi-4gi-4hi-4i2+2bj-4ij+2ck-4ik+2dl-4il+2em-4im+2fn-4in+io de+cf+bg-2bh-2ch-2dh-2eh-2fh+bi+2fi+4gi-37hi-7i2+cj+2ej+4fj-35gj-16hj-34ij+3j2+3dk+4ek-35fk-14gk-36hk+6ik+5jk+32k2+2cl+4dl-34el-14fl-34gl+4hl+5il-37jl-19kl-21l2+2bm+4cm-35dm-14em-33fm+6gm+3hm-37im-19jm-42km-5lm+46m2-39cn-18dn-38en+2fn+2gn-43hn-23in-46jn-9kn-13ln+43mn+27n2-15bo+41co-34do-38eo+29fo-35go+23ho+50io-3jo+15ko+3lo-39mo-9no d2+2ce+2bf-4bg-4cg-4dg-4eg+2bh+4eh+8fh+2ci+4di+8ei+4fi-4gi-23hi+18i2+4cj+10dj+4ej-27gj+36hj-25ij-2j2+4bk+8ck+4dk+2ek-23fk+32gk-25hk-4ik-2jk+41k2-4cl-8dl-31el+30fl-37gl-12hl-10il-27jl+38kl+38l2-8bm-16cm-39dm+20em-41fm-22gm-18hm-35im+30jm-25km-6lm-3m2-27cn+28dn-33en-12fn-14gn-25hn+38in-17jn+10kn+10ln-9mn+35n2+30bo+19co-33do-25eo+43fo-30go-45ho+io+6jo-30ko-4lo-19mo+22no cd+be-2bf-2cf-2df+bg+2dg+4eg+3ch+4dh+2eh-2fh+2bi+4ci+3di-2fi-2cj-4dj-3ej-6fj-4gj-4hj-4ij-4j2-4bk-8ck-8dk-8ek-9fk-8gk-8hk-8ik-12jk-8k2-2cl-4dl-4el-6fl-3gl-4hl-4il-8jl-12kl-4l2+2bm+4cm+2dm-2fm+hm-4jm-8km-4lm+2cn+4dn+2en-2fn+in-4jn-8kn-4ln-50fo+jo+2ko+lo c2+2bd-4be-4ce+2bf+4cf+8df+4bg+10cg+4dg-4eg-4ch-6dh-12eh-8fh-8bi-16ci-16di-18ei-8fi+38hi-44i2-4cj-8dj-4ej+10fj-47gj+29hj+42ij+4j2+4bk+8ck+12dk+12ek-39fk+47gk-43hk+8ik+12jk+27k2+12cl+24dl-39el+45fl-35gl+18hl+4il+46jl+25kl+17l2+8bm+16cm-35dm+49em-31fm+24gm+12hm+40im+17jm+34km-20lm-18m2+46cn+29dn+50en+16fn+8gn+30hn-7in+12jn-36kn+49ln-30mn+7n2+41bo-38co-35do-50eo+15fo-39go-9ho+2io-10jo-41ko+12lo+46mo-36no bc-2bd+3be+4ce-cf-6df-4bg-8cg-5dg+2ch+2dh+9eh+8fh+6bi+12ci+12di+16ei+9fi-19hi+22i2+6cj+10dj+6ej-4fj-30gj+32hj-25ij-6j2-4dk-4ek-33fk+20gk-36hk-12ik-18jk+29k2-8cl-18dl-37el+20fl-47gl-24hl-17il-43jl+14kl+26l2-8bm-16cm-45dm+12em+50fm-32gm-28hm-43im+15jm-49km-30lm-15m2-27cn+26dn-37en-24fn-24gn-35hn+32in-33jn-13kn-14ln-33mn+23n2+30bo+19co+18do-25eo+44fo-29go-44ho+io+8jo-26ko-15mo+26no b2+2bd-2ce+2df+4bg+4cg+4dg+2eg-4eh-6fh-4ci-4di-8ei-4fi+2gi-25hi+13i2-4cj-8dj-4ej-21gj+28hj-49ij-24j2-4ck-21fk+34gk-45hk-46ik+29jk-10k2+4cl+8dl-17el+34fl-37gl-40hl+33il-18jl+7kl-46l2+8bm+12cm-9dm+42em-33fm-32gm+41hm-12im+11jm+11km-14lm-31m2-21cn+34dn-41en-40fn+37gn-20hn+3in+jn-26kn+25ln-50mn+19n2-19bo+26co+33do+3eo+36fo+31go-10ho+12io-4jo+43ko-49lo+23mo-40no mathicgb-master/examples/hkatsura-101/hkatsura14-101/hkatsura14-101.ideal000066400000000000000000000012451311555162500256460ustar00rootroot00000000000000101 15 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n-o a2+2b2+2c2+2d2+2e2+2f2+2g2+2h2+2i2+2j2+2k2+2l2+2m2+2n2-ao 2ab+2bc+2cd+2de+2ef+2fg+2gh+2hi+2ij+2jk+2kl+2lm+2mn-bo b2+2ac+2bd+2ce+2df+2eg+2fh+2gi+2hj+2ik+2jl+2km+2ln-co 2bc+2ad+2be+2cf+2dg+2eh+2fi+2gj+2hk+2il+2jm+2kn-do c2+2bd+2ae+2bf+2cg+2dh+2ei+2fj+2gk+2hl+2im+2jn-eo 2cd+2be+2af+2bg+2ch+2di+2ej+2fk+2gl+2hm+2in-fo d2+2ce+2bf+2ag+2bh+2ci+2dj+2ek+2fl+2gm+2hn-go 2de+2cf+2bg+2ah+2bi+2cj+2dk+2el+2fm+2gn-ho e2+2df+2cg+2bh+2ai+2bj+2ck+2dl+2em+2fn-io 2ef+2dg+2ch+2bi+2aj+2bk+2cl+2dm+2en-jo f2+2eg+2dh+2ci+2bj+2ak+2bl+2cm+2dn-ko 2fg+2eh+2di+2cj+2bk+2al+2bm+2cn-lo g2+2fh+2ei+2dj+2ck+2bl+2am+2bn-mo mathicgb-master/examples/hkatsura-101/hkatsura15-101/000077500000000000000000000000001311555162500223575ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura15-101/hkatsura15-101-trimmed.ideal000066400000000000000000000074071311555162500273150ustar00rootroot00000000000000101 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 15 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n+2o-p hi+8i2+gj+16hj+45ij+44j2+fk+16gk+45hk-13ik+44jk+7k2+el+16fl+45gl-13hl+44il+14jl-2kl-2l2+dm+16em+45fm-13gm+44hm+14im-2jm-4km+8lm+17m2+cn+16dn+45en-13fn+44gn+14hn-2in-4jn+8kn+34ln-27mn-37n2+bo+16co+45do-13eo+44fo+14go-2ho-4io+8jo+34ko-27lo+27mo-6no+38o2+47bp-14cp+19dp+45ep-37fp-25gp-20hp-22ip-31jp-47kp+31lp+mp-36np+21op h2+2gi-15i2+2fj-30hj+13ij+14j2+2ek-30gk+13hk+28ik+15jk-13k2+2dl-30fl+13gl+28hl+15il-26jl+6kl+5l2+2cm-30em+13fm+28gm+15hm-26im+6jm+10km-14lm-33m2+2bn-30dn+13en+28fn+15gn-26hn+6in+10jn-14kn+35ln-45mn-26n2-4bo-34co+9do+24eo+11fo-30go+2ho+6io-18jo+31ko-49lo+45mo+10no+22o2+7bp+28cp-38dp+11ep-27fp+50gp+40hp+44ip-39jp-7kp+39lp-2mp-29np-41op gh+fi+ej+dk+cl+bm-2bn-2cn-2dn-2en-2fn-2gn-2hn-2in-2jn-2kn-2ln-2mn-2n2+bo-2no-50np g2+2fh+2ei+2dj+2ck+2bl-4bm-4cm-4dm-4em-4fm-4gm-4hm-4im-4jm-4km-4lm-4m2+2bn-4mn+2co-4mo+mp fg+eh+di+cj+bk-2bl-2cl-2dl-2el-2fl-2gl-2hl-2il-2jl-2kl-2l2+bm-2lm+cn-2ln+do-2lo-50lp f2+2eg+2dh+2ci+2bj-4bk-4ck-4dk-4ek-4fk-4gk-4hk-4ik-4jk-4k2+2bl-4kl+2cm-4km+2dn-4kn+2eo-4ko+kp ef+dg+ch+bi-2bj-2cj-2dj-2ej-2fj-2gj-2hj-2ij-2j2+bk-2jk+cl-2jl+dm-2jm+en-2jn+fo-2jo-50jp e2+2df+2cg+2bh-4bi-4ci-4di-4ei-4fi-4gi+28i2+2bj+4gj-37hj-26ij-26j2+2ck+4fk-37gk-22hk+45ik-26jk+28k2+2dl+4el-37fl-22gl+49hl-30il-45jl-8kl-8l2+4dm-35em-22fm+49gm-26hm-49im-8jm-16km+32lm-33m2+4cn-37dn-22en-50fn-26gn-45hn-12in-16jn+32kn+35ln-7mn-47n2+4bo-37co-22do+49eo-26fo-43go-8ho-20io+32jo+35ko-7lo+7mo-24no-50o2-14bp+45cp-25dp-22ep-47fp+gp+21hp+14ip-23jp+14kp+23lp+4mp-43np-17op de+cf+bg-2bh-2ch-2dh-2eh-2fh+bi+2fi+4gi-14i2+cj+2ej+4fj+2gj-30hj+15ij+15j2+3dk+4ek+2fk-28gk+13hk+30ik+17jk-12k2+2cl+4dl+3el-28fl+15gl+28hl+17il-24jl+8kl+6l2+2bm+4cm+2dm-28em+16fm+30gm+15hm-24im+8jm+12km-12lm-32m2-2cn-32dn+11en+26fn+14gn-30hn+4in+8jn-16kn+33ln-47mn-29n2-4bo-36co+7do+22eo+9fo-32go-ho+4io-20jo+29ko+50lo+43mo+4no+19o2+7bp+28cp-38dp+11ep-27fp+50gp-10hp+44ip-39jp-7kp+39lp-2mp-28np-40op d2+2ce+2bf-4bg-4cg-4dg-4eg+2bh+4eh+8fh+2ci+4di+8ei+4fi-4gi+4cj+10dj+4ej-4gj+4bk+8ck+4dk+2ek-4gk-4cl-8dl-8el-6fl-12gl-8hl-8il-8jl-8kl-8l2-8bm-16cm-16dm-16em-16fm-18gm-16hm-16im-16jm-16km-24lm-16m2-4cn-8dn-8en-8fn-12gn-6hn-8in-8jn-8kn-16ln-24mn-8n2+4bo+8co+4do-4go+2io-8lo-16mo-8no+gp+2lp+4mp+2np cd+be-2bf-2cf-2df+bg+2dg+4eg+3ch+4dh+2eh-2fh+2bi+4ci+3di-2fi-2cj-4dj-3ej-6fj-4gj-4hj-4ij-4j2-4bk-8ck-8dk-8ek-9fk-8gk-8hk-8ik-12jk-8k2-2cl-4dl-4el-6fl-3gl-4hl-4il-8jl-12kl-4l2+2bm+4cm+2dm-2fm+hm-4jm-8km-4lm+2cn+4dn+2en-2fn+in-4jn-8kn-4ln+2do+4eo-3jo-8ko-4lo-50fp+jp+2kp+lp c2+2bd-4be-4ce+2bf+4cf+8df+4bg+10cg+4dg-4eg-4ch-6dh-12eh-8fh-8bi-16ci-16di-18ei-8fi-45i2-4cj-8dj-4ej+10fj+16gj+27hj+49ij+49j2+4bk+8ck+12dk+12ek+24fk+45gk-36hk-3ik-44jk-37k2+12cl+24dl+24el+43fl-28gl+7hl+49il+19jl-8l2+8bm+16cm+28dm+47em-24fm+13gm-44hm+13im-8jm-16km-21lm+43m2+8cn+27dn-44en+5fn-48gn+3hn-32in-38jn-37kn-31ln-14mn-n2+11co+41do-23eo+37fo+3go-36ho+37io+40jo-45ko-30lo-2mo+21no-23o2-28bp-11cp-50dp-43ep+7fp+2gp+44hp+30ip-44jp+28kp+46lp+8mp+19np-26op bc-2bd+3be+4ce-cf-6df-4bg-8cg-5dg+2ch+2dh+9eh+8fh+6bi+12ci+12di+16ei+9fi-28i2+6cj+10dj+6ej-4fj-11gj+33hj+22ij+22j2-4dk-4ek-14fk+21gk+11hk+44ik+10jk-40k2-8cl-18dl-18el+21fl+32hl+11il+21jl-24kl-12l2-8bm-16cm-26dm+13em-4fm+24gm+21im-23jm-24km+21lm+5m2-8cn+27dn+10en+32fn+4gn+29hn-6in-8jn+38kn+26ln-41mn+27n2+45co+24do-49eo+18fo+29go-2ho+12io-46jo+42ko-24lo-47mo-8no+38o2+14bp-45cp-25dp+22ep+48fp+gp-20hp-13ip+25jp-10kp-17lp+4mp+49np+21op b2+2bd-2ce+2df+4bg+4cg+4dg+2eg-4eh-6fh-4ci-4di-8ei-4fi+2gi+11i2-4cj-8dj-4ej+4gj+24hj-35ij-35j2-4ck+4fk+30gk-31hk+33ik+18jk-37k2+4cl+8dl+8el+30fl-23gl+39hl+22il+29jl-43kl+5l2+8bm+12cm+16dm+38em-19fm+47gm+30hm+35im-39jm+12km-16lm-10m2+4cn+30dn-27en+39fn+26gn+27hn-47in+2jn-28kn-34ln-18mn+3n2+18co-35do+31eo+18fo+27go+50ho-6io-36jo-44ko-30lo+8mo-49no-41o2+45bp-21cp+3dp+17ep+20fp+12gp-5hp-33ip+29jp-21kp+19lp+48mp-31np-20op mathicgb-master/examples/hkatsura-101/hkatsura15-101/hkatsura15-101.ideal000066400000000000000000000014011311555162500256420ustar00rootroot00000000000000101 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 15 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n+2o-p a2+2b2+2c2+2d2+2e2+2f2+2g2+2h2+2i2+2j2+2k2+2l2+2m2+2n2+2o2-ap 2ab+2bc+2cd+2de+2ef+2fg+2gh+2hi+2ij+2jk+2kl+2lm+2mn+2no-bp b2+2ac+2bd+2ce+2df+2eg+2fh+2gi+2hj+2ik+2jl+2km+2ln+2mo-cp 2bc+2ad+2be+2cf+2dg+2eh+2fi+2gj+2hk+2il+2jm+2kn+2lo-dp c2+2bd+2ae+2bf+2cg+2dh+2ei+2fj+2gk+2hl+2im+2jn+2ko-ep 2cd+2be+2af+2bg+2ch+2di+2ej+2fk+2gl+2hm+2in+2jo-fp d2+2ce+2bf+2ag+2bh+2ci+2dj+2ek+2fl+2gm+2hn+2io-gp 2de+2cf+2bg+2ah+2bi+2cj+2dk+2el+2fm+2gn+2ho-hp e2+2df+2cg+2bh+2ai+2bj+2ck+2dl+2em+2fn+2go-ip 2ef+2dg+2ch+2bi+2aj+2bk+2cl+2dm+2en+2fo-jp f2+2eg+2dh+2ci+2bj+2ak+2bl+2cm+2dn+2eo-kp 2fg+2eh+2di+2cj+2bk+2al+2bm+2cn+2do-lp g2+2fh+2ei+2dj+2ck+2bl+2am+2bn+2co-mp 2gh+2fi+2ej+2dk+2cl+2bm+2an+2bo-np mathicgb-master/examples/hkatsura-101/hkatsura16-101/000077500000000000000000000000001311555162500223605ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura16-101/hkatsura16-101-trimmed.ideal000066400000000000000000000104331311555162500273100ustar00rootroot00000000000000101 17 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 16 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n+2o+2p-q i2+2hj-48ij+26j2+2gk-48hk-49ik-jk+48k2+2fl-48gl-49hl-il-5jl+40kl-34l2+2em-48fm-49gm-hm-5im+40jm+33km-26lm-18m2+2dn-48en-49fn-gn-5hn+40in+33jn-26kn-36ln+3mn-5n2+2co-48do-49eo-fo-5go+40ho+33io-26jo-36ko+3lo-10mo+26no+5o2+2bp-48cp-49dp-ep-5fp+40gp+33hp-26ip-36jp+3kp-10lp+26mp+10np+43op+12p2+13bq-49cq+16dq+6eq+22fq-37gq+31hq+24iq+43jq-13kq-43lq-47mq-25nq+23oq-4pq hi+gj+25ij+38j2+fk+25hk-25ik-49jk+27k2+el+25gl-25hl-49il-47jl-19kl-33l2+dm+25fm-25gm-49hm-47im-19jm+35km+14lm-41m2+cn+25en-25fn-49gn-47hn-19in+35jn+14kn+19ln+50mn+3n2+bo+25do-25eo-49fo-47go-19ho+35io+14jo+19ko+50lo+6mo-12no-2o2-2bp+23cp-27dp+50ep-49fp-21gp+33hp+12ip+17jp+48kp+4lp-14mp-6np+28op+43p2+44bq-26cq-8dq-3eq-11fq-32gq+35hq-12iq+29jq-44kq-29lq-27mq-38nq+39oq-48pq h2+2gi+2fj+2ek+2dl+2cm+2bn-4bo-4co-4do-4eo-4fo-4go-4ho-4io-4jo-4ko-4lo-4mo-4no-4o2+2bp-4op+oq gh+fi+ej+dk+cl+bm-2bn-2cn-2dn-2en-2fn-2gn-2hn-2in-2jn-2kn-2ln-2mn-2n2+bo-2no+cp-2np-50nq g2+2fh+2ei+2dj+2ck+2bl-4bm-4cm-4dm-4em-4fm-4gm-4hm-4im-4jm-4km-4lm-4m2+2bn-4mn+2co-4mo+2dp-4mp+mq fg+eh+di+cj+bk-2bl-2cl-2dl-2el-2fl-2gl-2hl-2il-2jl-2kl-2l2+bm-2lm+cn-2ln+do-2lo+ep-2lp-50lq f2+2eg+2dh+2ci+2bj-4bk-4ck-4dk-4ek-4fk-4gk-4hk-4ik-4jk-4k2+2bl-4kl+2cm-4km+2dn-4kn+2eo-4ko+2fp-4kp+kq ef+dg+ch+bi-2bj-2cj-2dj-2ej-2fj-2gj-2hj-2ij-2j2+bk-2jk+cl-2jl+dm-2jm+en-2jn+fo-2jo+gp-2jp-50jq e2+2df+2cg+2bh-4bi-4ci-4di-4ei-4fi-4gi+2bj+4gj+8hj+5ij-47j2+2ck+4fk+8gk+9hk+3ik+2jk-3k2+2dl+4el+8fl+9gl+7hl-2il-6jl-17kl+35l2+4dm+10em+9fm+7gm+2hm-10im-17jm-31km-48lm-34m2+4cn+8dn+9en+9fn+2gn-6hn-21in-31jn-48kn+33ln+10mn-8n2+4bo+8co+9do+7eo+2fo-4go-17ho-35io-48jo+33ko+10lo-16mo-45no+12o2+cp-dp-6ep-14fp-25gp-37hp+41ip+25jp+2kp-24lp+48mp+16np-19op+18p2+26bq+3cq+32dq+12eq+44fq+27gq-39hq+49iq-15jq-26kq+15lq+7mq-50nq+46oq-6pq de+cf+bg-2bh-2ch-2dh-2eh-2fh+bi+2fi+4gi+cj+2ej+4fj+2gj-2hj+50ij-25j2+3dk+4ek+2fk+48hk-50ik+3jk-47k2+2cl+4dl+3el+50gl+49hl+3il+7jl-38kl+35l2+2bm+4cm+2dm-50fm-50gm+hm+7im-38jm-31km+28lm+19m2-2cn-4dn+46en+47fn+hn-42in-35jn+24kn+34ln-5mn+2n2-4bo-8co+42do+43eo-5fo-go-47ho-39io+20jo+30ko-9lo+4mo-36no-12o2+48cp+47dp-ep+3fp-42gp-37hp+25ip+34jp-5kp+8lp-28mp-16np+48op-15p2-13bq+49cq-16dq-6eq-22fq+37gq+20hq-24iq-43jq+13kq+43lq+47mq+26nq-21oq+5pq d2+2ce+2bf-4bg-4cg-4dg-4eg+2bh+4eh+8fh+2ci+4di+8ei+4fi-4gi+4cj+10dj+4ej-4gj+4bk+8ck+4dk+2ek-4gk-4cl-8dl-8el-6fl-12gl-8hl-8il-8jl-8kl-8l2-8bm-16cm-16dm-16em-16fm-18gm-16hm-16im-16jm-16km-24lm-16m2-4cn-8dn-8en-8fn-12gn-6hn-8in-8jn-8kn-16ln-24mn-8n2+4bo+8co+4do-4go+2io-8lo-16mo-8no+4cp+8dp+4ep-4gp+2jp-8lp-16mp-8np+gq+2lq+4mq+2nq cd+be-2bf-2cf-2df+bg+2dg+4eg+3ch+4dh+2eh-2fh+2bi+4ci+3di-2fi-2cj-4dj-3ej-6fj-4gj-4hj-4ij-4j2-4bk-8ck-8dk-8ek-9fk-8gk-8hk-8ik-12jk-8k2-2cl-4dl-4el-6fl-3gl-4hl-4il-8jl-12kl-4l2+2bm+4cm+2dm-2fm+hm-4jm-8km-4lm+2cn+4dn+2en-2fn+in-4jn-8kn-4ln+2do+4eo-3jo-8ko-4lo+2ep+2fp+2gp-4jp-7kp-4lp-50fq+jq+2kq+lq c2+2bd-4be-4ce+2bf+4cf+8df+4bg+10cg+4dg-4eg-4ch-6dh-12eh-8fh-8bi-16ci-16di-18ei-8fi-4cj-8dj-4ej+10fj+16gj+16hj+10ij+7j2+4bk+8ck+12dk+12ek+24fk+34gk+26hk+14ik+12jk+2k2+12cl+24dl+24el+32fl+34gl+24hl+4il-4jl-18kl-23l2+8bm+16cm+28dm+36em+38fm+30gm+12hm-10im-26jm-46km+21lm+41m2+8cn+16dn+18en+22fn+8gn-20hn-50in+33jn+5kn-35ln+20mn-24n2+2do-6eo-8fo-20go+47ho+7io-19jo-49ko+4lo-48mo-21no-6cp-18dp-32ep-44fp+39gp+7hp-39ip+26jp-12kp+39lp-21mp+15op+12p2-49bq+6cq-37dq+25eq-13fq-47gq+25hq-iq-28jq+49kq+30lq+14mq+5nq-oq-4pq bc-2bd+3be+4ce-cf-6df-4bg-8cg-5dg+2ch+2dh+9eh+8fh+6bi+12ci+12di+16ei+9fi+6cj+10dj+6ej-4fj-11gj-12hj-9ij+43j2-4dk-4ek-14fk-24gk-20hk-15ik-18jk-9k2-8cl-18dl-18el-24fl-31gl-27hl-17il-18jl-15kl+46l2-8bm-16cm-26dm-32em-35fm-35gm-28hm-18im-14jm-9km+6m2-8cn-18dn-21en-27fn-24gn-10hn+3in+7jn+17kn+28ln+43mn-12n2-7do-7eo-10fo-10go+7ho+27io+34jo+44ko-41lo-24mo+13no-24o2+3cp+7dp+10ep+10fp+13gp+27hp+50ip-37jp-24kp-8lp+14mp-48np-5op-30p2-26bq-3cq+19dq-12eq-43fq-25gq+40hq-48iq+17jq+30kq-9lq+mq-45nq-42oq+10pq b2+2bd-2ce+2df+4bg+4cg+4dg+2eg-4eh-6fh-4ci-4di-8ei-4fi+2gi-4cj-8dj-4ej+4gj+2hj-12ij-18j2-4ck+4fk+8gk-8hk-34ik+29jk+41k2+4cl+8dl+8el+8fl-28hl+33il-17jl+22kl-25l2+8bm+12cm+16dm+16em+4fm-20gm+41hm-11im+26jm-48km-33lm-14m2+4cn+8dn-4en-28fn+37gn-19hn+18in+43jn-45kn-42ln+50mn-43n2-4co-12do-36eo+29fo-19go+14ho+35io+48jo+49ko+38lo+17mo-32no+5o2-16cp-44dp+21ep-27fp+14gp+35hp+44ip+41jp+30kp+7lp-28mp+12np+40op+29p2+3bq+13cq+29dq-49eq-20fq+15gq-43hq+6iq-40jq+21kq-13lq-41mq+42nq+30oq+24pq mathicgb-master/examples/hkatsura-101/hkatsura16-101/hkatsura16-101.ideal000066400000000000000000000015441311555162500256540ustar00rootroot00000000000000101 17 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 16 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n+2o+2p-q a2+2b2+2c2+2d2+2e2+2f2+2g2+2h2+2i2+2j2+2k2+2l2+2m2+2n2+2o2+2p2-aq 2ab+2bc+2cd+2de+2ef+2fg+2gh+2hi+2ij+2jk+2kl+2lm+2mn+2no+2op-bq b2+2ac+2bd+2ce+2df+2eg+2fh+2gi+2hj+2ik+2jl+2km+2ln+2mo+2np-cq 2bc+2ad+2be+2cf+2dg+2eh+2fi+2gj+2hk+2il+2jm+2kn+2lo+2mp-dq c2+2bd+2ae+2bf+2cg+2dh+2ei+2fj+2gk+2hl+2im+2jn+2ko+2lp-eq 2cd+2be+2af+2bg+2ch+2di+2ej+2fk+2gl+2hm+2in+2jo+2kp-fq d2+2ce+2bf+2ag+2bh+2ci+2dj+2ek+2fl+2gm+2hn+2io+2jp-gq 2de+2cf+2bg+2ah+2bi+2cj+2dk+2el+2fm+2gn+2ho+2ip-hq e2+2df+2cg+2bh+2ai+2bj+2ck+2dl+2em+2fn+2go+2hp-iq 2ef+2dg+2ch+2bi+2aj+2bk+2cl+2dm+2en+2fo+2gp-jq f2+2eg+2dh+2ci+2bj+2ak+2bl+2cm+2dn+2eo+2fp-kq 2fg+2eh+2di+2cj+2bk+2al+2bm+2cn+2do+2ep-lq g2+2fh+2ei+2dj+2ck+2bl+2am+2bn+2co+2dp-mq 2gh+2fi+2ej+2dk+2cl+2bm+2an+2bo+2cp-nq h2+2gi+2fj+2ek+2dl+2cm+2bn+2ao+2bp-oq mathicgb-master/examples/hkatsura-101/hkatsura17-101/000077500000000000000000000000001311555162500223615ustar00rootroot00000000000000mathicgb-master/examples/hkatsura-101/hkatsura17-101/hkatsura17-101-trimmed.ideal000066400000000000000000000124041311555162500273120ustar00rootroot00000000000000101 18 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 17 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n+2o+2p+2q-r ij+50j2+hk-ik-6jk-7k2+gl-hl-6il-14jl-25kl+31l2+fm-gm-6hm-14im-25jm-39km+45lm-38m2+en-fn-6gn-14hn-25in-39jn+45kn+25ln+2mn-12n2+do-eo-6fo-14go-25ho-39io+45jo+25ko+2lo-24mo+48no+8o2+cp-dp-6ep-14fp-25gp-39hp+45ip+25jp+2kp-24lp+48mp+16np-19op+22p2+bq-cq-6dq-14eq-25fq-39gq+45hq+25iq+2jq-24kq+48lq+16mq-19nq+44oq+3pq+30q2+26br+3cr+32dr+12er+44fr+27gr-39hr+48ir-15jr-26kr+15lr+7mr-50nr+46or-8pr-10qr i2+2hj+2j2+2gk+4ik+14jk+15k2+2fl+4hl+14il+30jl-49kl+40l2+2em+4gm+14hm+30im-49jm-21km+13lm-24m2+2dn+4fn+14gn+30hn-49in-21jn+13kn-48ln-2mn+25n2+2co+4eo+14fo+30go-49ho-21io+13jo-48ko-2lo+50mo+7no-15o2+2bp+4dp+14ep+30fp-49gp-21hp+13ip-48jp-2kp+50lp+7mp-30np+40op-43p2-4bq+10dq+26eq+48fq-25gq+9hq+49iq-6jq+46kq+3lq-34mq+36nq+11oq-8pq+38q2+49br-6cr+37dr-24er+13fr+47gr-23hr+5ir+30jr-49kr-30lr-14mr-nr+9or+16pr+21qr hi+gj+fk+el+dm+cn+bo-2bp-2cp-2dp-2ep-2fp-2gp-2hp-2ip-2jp-2kp-2lp-2mp-2np-2op-2p2+bq-2pq-50pr h2+2gi+2fj+2ek+2dl+2cm+2bn-4bo-4co-4do-4eo-4fo-4go-4ho-4io-4jo-4ko-4lo-4mo-4no-4o2+2bp-4op+2cq-4oq+or gh+fi+ej+dk+cl+bm-2bn-2cn-2dn-2en-2fn-2gn-2hn-2in-2jn-2kn-2ln-2mn-2n2+bo-2no+cp-2np+dq-2nq-50nr g2+2fh+2ei+2dj+2ck+2bl-4bm-4cm-4dm-4em-4fm-4gm-4hm-4im-4jm-4km-4lm-4m2+2bn-4mn+2co-4mo+2dp-4mp+2eq-4mq+mr fg+eh+di+cj+bk-2bl-2cl-2dl-2el-2fl-2gl-2hl-2il-2jl-2kl-2l2+bm-2lm+cn-2ln+do-2lo+ep-2lp+fq-2lq-50lr f2+2eg+2dh+2ci+2bj-4bk-4ck-4dk-4ek-4fk-4gk-4hk-4ik-4jk-4k2+2bl-4kl+2cm-4km+2dn-4kn+2eo-4ko+2fp-4kp+2gq-4kq+kr ef+dg+ch+bi-2bj-2cj-2dj-2ej-2fj-2gj-2hj-3j2+bk+2hk-2ik-14jk-14k2+cl+2gl-2hl-12il-30jl-50kl-39l2+dm+2fm-2gm-12hm-28im+49jm+23km-11lm+25m2+3en-2fn-12gn-28hn-50in+21jn-11kn+50ln+4mn-24n2+2do-2eo-11fo-28go-50ho+23io-13jo+50ko+4lo-48mo-5no+16o2+2cp-2dp-12ep-28fp-49gp+23hp-11ip+48jp+4kp-48lp-5mp+32np-38op+44p2+2bq-2cq-12dq-28eq-50fq+23gq-10hq+50iq+2jq-48kq-5lq+32mq-38nq-13oq+6pq-41q2-49br+6cr-37dr+24er-13fr-47gr+23hr-5ir+21jr+49kr+30lr+14mr+nr-9or-16pr-20qr e2+2df+2cg+2bh-4bi-4ci-4di-4ei-4fi-4gi+2bj+4gj+8hj+6j2+2ck+4fk+8gk+4hk+8ik+32jk+32k2+2dl+4el+8fl+4gl+12hl+28il-37jl+7kl-19l2+4dm+10em+4fm+12gm+32hm-41im+7jm-38km+30lm-46m2+4cn+8dn+4en+14fn+32gn-37hn+3in-38jn+30kn+9ln-49n2+4bo+8co+4do+12eo+32fo-35go+7ho-42io+30jo+9ko+3mo+18no-28o2-4cp+4dp+24ep-45fp-gp-44hp+18ip+jp-8kp-5lp+10mp+37np-25op+9p2-8bq-4cq+16dq+48eq-9fq+47gq+14hq-9iq-16jq-13kq+2lq+29mq-33nq+18oq-28pq-31q2-3br-12cr-27dr-48er+26fr-7gr-46hr+11ir-41jr+3kr+41lr-28mr-2nr+18or+34pr+44qr de+cf+bg-2bh-2ch-2dh-2eh-2fh+bi+2fi+4gi+cj+2ej+4fj+2gj-2hj+3dk+4ek+2fk-2hk+2cl+4dl+3el-2hl+2bm+4cm+2dm+fm-2hm-2cn-4dn-4en-4fn-3gn-6hn-4in-4jn-4kn-4ln-4mn-4n2-4bo-8co-8do-8eo-8fo-8go-9ho-8io-8jo-8ko-8lo-8mo-12no-8o2-2cp-4dp-4ep-4fp-4gp-6hp-3ip-4jp-4kp-4lp-4mp-8np-12op-4p2+2bq+4cq+2dq-2hq+jq-4nq-8oq-4pq-50hr+nr+2or+pr d2+2ce+2bf-4bg-4cg-4dg-4eg+2bh+4eh+8fh+2ci+4di+8ei+4fi-4gi+4cj+10dj+4ej-4gj+4bk+8ck+4dk+2ek-4gk-4cl-8dl-8el-6fl-12gl-8hl-8il-8jl-8kl-8l2-8bm-16cm-16dm-16em-16fm-18gm-16hm-16im-16jm-16km-24lm-16m2-4cn-8dn-8en-8fn-12gn-6hn-8in-8jn-8kn-16ln-24mn-8n2+4bo+8co+4do-4go+2io-8lo-16mo-8no+4cp+8dp+4ep-4gp+2jp-8lp-16mp-8np+4dq+8eq+4fq-4gq+2kq-8lq-16mq-8nq+gr+2lr+4mr+2nr cd+be-2bf-2cf-2df+bg+2dg+4eg+3ch+4dh+2eh-2fh+2bi+4ci+3di-2fi-2cj-4dj-3ej-6fj-4gj-4hj-6j2-4bk-8ck-8dk-8ek-9fk-8gk-4hk-12ik-36jk-36k2-2cl-4dl-4el-6fl+gl-8hl-28il+37jl-11kl+19l2+2bm+4cm+2dm+2fm-4gm-23hm+45im-3jm+38km-26lm+50m2+2cn+4dn+6en-6fn-24gn+45hn+2in+42jn-30kn-5ln+8mn-48n2+6do-24fo+45go+ho+46io-25jo-9ko+4lo+5mo-10no+32o2+4cp-4dp-22ep+47fp+3gp+46hp-22ip-5jp+kp+lp-10mp-37np+25op-13p2+4bq-4cq-24dq+45eq+fq+50gq-20hq-iq+4jq-3kq-13lq-37mq+25nq-26oq+12pq+19q2+3br+12cr+27dr+48er+25fr+7gr+46hr-10ir+42jr-kr-40lr+28mr+2nr-18or-32pr-40qr c2+2bd-4be-4ce+2bf+4cf+8df+4bg+10cg+4dg-4eg-4ch-6dh-12eh-8fh-8bi-16ci-16di-18ei-8fi-4cj-8dj-4ej+10fj+16gj+16hj+12j2+4bk+8ck+12dk+12ek+24fk+34gk+16hk+24ik-29jk-29k2+12cl+24dl+24el+32fl+24gl+34hl-37il+35jl+30kl-30l2+8bm+16cm+28dm+36em+28fm+40gm-29hm+29im+22jm+41km-25lm+17m2+8cn+16dn+8en+32fn-33gn+19hn-2in+19jn-41kn+18ln-5n2-8do+4eo-49fo+19go-6ho-7io+36jo+4ko-16lo-10mo+4no+21o2-16cp-8dp+28ep-5fp-14gp-7hp+16ip-22jp-32kp-24lp+4mp+42np+3op-6p2-16bq-8cq+24dq-25eq-34fq-23gq+8hq-38iq+49jq-42kq-12lq+44mq+3nq-12oq-3pq+15q2-6br-24cr+47dr+6er-49fr-14gr+11hr+24ir+21jr+6kr-19lr+45mr+44or-25pr-5qr bc-2bd+3be+4ce-cf-6df-4bg-8cg-5dg+2ch+2dh+9eh+8fh+6bi+12ci+12di+16ei+9fi+6cj+10dj+6ej-4fj-11gj-12hj-12j2-4dk-4ek-14fk-24gk-11hk-24ik+29jk+29k2-8cl-18dl-18el-24fl-22gl-36hl+30il-43jl-38kl+22l2-8bm-16cm-26dm-32em-26fm-44gm+19hm-43im-37jm+44km+lm-33m2-8cn-18dn-12en-36fn+23gn-35hn-20in-41jn+18kn-50ln-40mn-19n2+2do-16eo+37fo-35go-16ho-21io+35jo-34ko-23lo-38mo+41no+48o2+12cp-2dp-44ep-15fp-10gp-21hp-50ip-14jp-6kp-22lp+42mp-5np+26op-34p2+12bq-38dq+5eq+10fq-9gq-44hq-2iq+10jq-2kq-42lq-5mq+27nq+33oq+16pq+38q2+6br+24cr+4dr-5er+50fr+16gr-8hr-20ir-17jr-2kr+25lr-37mr+10nr-32or+39pr+21qr b2+2bd-2ce+2df+4bg+4cg+4dg+2eg-4eh-6fh-4ci-4di-8ei-4fi+2gi-4cj-8dj-4ej+4gj+2hj-24j2-4ck+4fk+8gk+4hk-46ik-43jk-43k2+4cl+8dl+8el+8fl+12gl-40hl-39il+17jl+25kl+44l2+8bm+12cm+16dm+16em+16fm-32gm-31hm+23im+29jm-11km+2lm+35m2+4cn+8dn+8en-40fn-35gn+15hn+21in-21jn-10kn-45ln-27mn+15n2-4co-48eo-43fo+15go+17ho-29io-18jo+46ko-39lo+32mo+39no-4cp+45dp+50ep+7fp+17gp-29hp-22ip+38jp-47kp+22lp+43mp+2np+14op-10p2+49cq+50dq-eq+9fq-29gq-22hq+38iq+50jq+14kq+35lq+8mq+18nq-18oq-pq-15q2+12br+49cr+9dr-6er+3fr+36gr-6hr-24ir-18jr+12kr-35lr+43mr+48nr-24or+29pr+5qr mathicgb-master/examples/hkatsura-101/hkatsura17-101/hkatsura17-101.ideal000066400000000000000000000017141311555162500256550ustar00rootroot00000000000000101 18 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 17 a+2b+2c+2d+2e+2f+2g+2h+2i+2j+2k+2l+2m+2n+2o+2p+2q-r a2+2b2+2c2+2d2+2e2+2f2+2g2+2h2+2i2+2j2+2k2+2l2+2m2+2n2+2o2+2p2+2q2-ar 2ab+2bc+2cd+2de+2ef+2fg+2gh+2hi+2ij+2jk+2kl+2lm+2mn+2no+2op+2pq-br b2+2ac+2bd+2ce+2df+2eg+2fh+2gi+2hj+2ik+2jl+2km+2ln+2mo+2np+2oq-cr 2bc+2ad+2be+2cf+2dg+2eh+2fi+2gj+2hk+2il+2jm+2kn+2lo+2mp+2nq-dr c2+2bd+2ae+2bf+2cg+2dh+2ei+2fj+2gk+2hl+2im+2jn+2ko+2lp+2mq-er 2cd+2be+2af+2bg+2ch+2di+2ej+2fk+2gl+2hm+2in+2jo+2kp+2lq-fr d2+2ce+2bf+2ag+2bh+2ci+2dj+2ek+2fl+2gm+2hn+2io+2jp+2kq-gr 2de+2cf+2bg+2ah+2bi+2cj+2dk+2el+2fm+2gn+2ho+2ip+2jq-hr e2+2df+2cg+2bh+2ai+2bj+2ck+2dl+2em+2fn+2go+2hp+2iq-ir 2ef+2dg+2ch+2bi+2aj+2bk+2cl+2dm+2en+2fo+2gp+2hq-jr f2+2eg+2dh+2ci+2bj+2ak+2bl+2cm+2dn+2eo+2fp+2gq-kr 2fg+2eh+2di+2cj+2bk+2al+2bm+2cn+2do+2ep+2fq-lr g2+2fh+2ei+2dj+2ck+2bl+2am+2bn+2co+2dp+2eq-mr 2gh+2fi+2ej+2dk+2cl+2bm+2an+2bo+2cp+2dq-nr h2+2gi+2fj+2ek+2dl+2cm+2bn+2ao+2bp+2cq-or 2hi+2gj+2fk+2el+2dm+2cn+2bo+2ap+2bq-pr mathicgb-master/examples/hyclic8-101-trimmed.ideal000077500000000000000000000052151311555162500222560ustar00rootroot00000000000000101 9 1 1 1 1 1 1 1 1 1 1 8 a+b+c+d+e+f+g+h b2+bd-cd+be-de+bf-ef+bg-fg+2bh+ch+dh+eh+fh+h2 bc2-bcd+c2d+cef-def+cfg-efg-c2h-ceh+deh-cfh+efh+bgh+cgh+dgh+egh+fgh+g2h-bh2-2ch2-dh2-eh2-fh2+gh2-h3 bcd2-bcde+cd2e-cdef+d2ef-cd2h+cdeh-d2eh+bcgh-bdgh-d2gh+bfgh+cfgh+2efgh+f2gh-dg2h+2fg2h-bch2+bdh2+d2h2+dfh2-efh2-2bgh2-2cgh2-3dgh2-2egh2-fgh2-g2h2+bh3+ch3+2dh3+eh3+fh3-2gh3+h4 bcde2-bcdef+cde2f-cdefg+de2fg-cde2h+cdefh-de2fh+bcdgh-bcegh-de2gh+bcfgh+cdfgh+2defgh-e2fgh+ef2gh+f2g2h-bcdh2+bceh2+de2h2-defh2+e2fh2-2bcgh2-2cdgh2+2begh2+2cegh2+2e2gh2-2bfgh2-2cfgh2-2dfgh2-2efgh2-2f2gh2-bg2h2-cg2h2-dg2h2-3fg2h2-g3h2+bch3+cdh3-beh3-ceh3-e2h3+3bgh3+3cgh3+3dgh3+5egh3+fgh3-bh4-ch4-dh4-2eh4-fh4+3gh4-h5 bcdef2-bcdefg+cdef2g-cdef2h+bcdegh+bcefgh+bdefgh+3cdefgh+d2efgh+2de2fgh-bcf2gh-cdf2gh-bef2gh-cef2gh-def2gh-2ef3gh+2defg2h-f3g2h-bcdeh2+bcdfh2+def2h2-2bcdgh2-2cdegh2-2befgh2-2cefgh2-3defgh2-2e2fgh2+2bf2gh2+2cf2gh2+2df2gh2-ef2gh2+2f3gh2-bcg2h2-cdg2h2-deg2h2-bfg2h2-cfg2h2-dfg2h2-4efg2h2-2fg3h2+bcdh3+cdeh3-bcfh3-cdfh3-ef2h3+3bcgh3+3cdgh3+3degh3+efgh3+2f2gh3+3bg2h3+3cg2h3+3dg2h3+3eg2h3+3fg2h3+2g3h3-bch4-cdh4-deh4+bfh4+cfh4+dfh4+f2h4-4bgh4-4cgh4-4dgh4-4egh4-4fgh4+2g2h4+bh5+ch5+dh5+eh5+2fh5-4gh5+h6 bcdefg2+4bcdefgh+c2defgh+2cd2efgh+2cde2fgh+d2e2fgh+2cdef2gh+2de2f2gh-bcdeg2h-bcdfg2h-bcefg2h-bdefg2h-2cdefg2h-d2efg2h-2de2fg2h-2defg3h-2ef2g3h-bcdefh2-bcdegh2-2bcdfgh2-2bcefgh2-2bdefgh2-6cdefgh2-2d2efgh2-4de2fgh2-4def2gh2-2e2f2gh2+bcdg2h2+cdeg2h2-2defg2h2-bf2g2h2-cf2g2h2-df2g2h2-3ef2g2h2-f3g2h2+bcg3h2+cdg3h2+deg3h2+2bfg3h2+2cfg3h2+2dfg3h2+2efg3h2+3fg4h2+bcdeh3+cdefh3+2bcdgh3+2cdegh3+3bcfgh3+3cdfgh3+3befgh3+3cefgh3+6defgh3+3e2fgh3+6ef2gh3+3bfg2h3+3cfg2h3+3dfg2h3+5efg2h3+3f2g2h3-2bg3h3-2cg3h3-2dg3h3-2eg3h3+4fg3h3-g4h3-bcdh4-cdeh4-defh4-3bcgh4-3cdgh4-3degh4-4bfgh4-4cfgh4-4dfgh4-4efgh4-4f2gh4-2bg2h4-2cg2h4-2dg2h4-2eg2h4-fg2h4-4g3h4+bch5+cdh5+deh5+efh5+4bgh5+4cgh5+4dgh5+4egh5-g2h5-bh6-ch6-dh6-eh6-fh6+4gh6-h7 bcdefgh2-20c2defgh2-40cd2efgh2-40cde2fgh2-20d2e2fgh2-40cdef2gh2-40de2f2gh2-40cdefg2h2-40def2g2h2-20e2f2g2h2+20bcdefh3+40bcdegh3+40bcdfgh3+40bcefgh3+40bdefgh3+39cdefgh3+40d2efgh3-21de2fgh3-21def2gh3+40e2f2gh3+20bcdg2h3+20cdeg2h3+40bcfg2h3+40cdfg2h3+40befg2h3+40cefg2h3+39defg2h3+40e2fg2h3+20bf2g2h3+20cf2g2h3+20df2g2h3+39ef2g2h3+20f3g2h3-41efg3h3-41f2g3h3-20bcdeh4-20cdefh4+41bcdgh4+41cdegh4+41bcfgh4+41cdfgh4+41befgh4+41cefgh4-39defgh4+41e2fgh4-19ef2gh4+41bcg2h4+41cdg2h4+41deg2h4-19bfg2h4-19cfg2h4-19dfg2h4+22efg2h4-19f2g2h4-20bg3h4-20cg3h4-20dg3h4-20eg3h4-39fg3h4-20g4h4+20bcdh5+20cdeh5+20defh5-21bcgh5-21cdgh5-21degh5-21bfgh5-21cfgh5-21dfgh5-efgh5-21f2gh5+19bg2h5+19cg2h5+19dg2h5+19eg2h5+40fg2h5+40g3h5-20bch6-20cdh6-20deh6-20efh6+bgh6+cgh6+dgh6+egh6-20fgh6-g2h6+20bh7+20ch7+20dh7+20eh7+20fh7+gh7+20h8+20i8 mathicgb-master/examples/hyclic9-101-trimmed.ideal000066400000000000000000000127741311555162500222640ustar00rootroot00000000000000101 10 1 1 1 1 1 1 1 1 1 1 1 9 a+b+c+d+e+f+g+h+i b2+bd-cd+be-de+bf-ef+bg-fg+bh-gh+2bi+ci+di+ei+fi+gi+i2 bc2-bcd+c2d+cef-def+cfg-efg+cgh-fgh-c2i-cei+dei-cfi+efi-cgi+fgi+bhi+chi+dhi+ehi+fhi+ghi+h2i-bi2-2ci2-di2-ei2-fi2-gi2+hi2-i3 bcd2-bcde+cd2e-cdef+d2ef+dfgh-efgh-cd2i+cdei-d2ei-dfgi+efgi+bchi-bdhi-d2hi-dfhi+efhi+bghi+cghi+eghi+2fghi+g2hi-dh2i+2gh2i-bci2+bdi2+d2i2+dfi2-efi2+dgi2-fgi2-2bhi2-2chi2-3dhi2-2ehi2-2fhi2-ghi2-h2i2+bi3+ci3+2di3+ei3+fi3+gi3-2hi3+i4 bcde2-bcdef+cde2f-cdefg+de2fg-defgh+e2fgh-cde2i+cdefi-de2fi+defgi-e2fgi+bcdhi-bcehi-de2hi+defhi-e2fhi+bcghi+cdghi-beghi-ceghi-e2ghi+bfghi+cfghi+dfghi+efghi+f2ghi-eg2hi+2fg2hi-2egh2i+2fgh2i+g2h2i-bcdi2+bcei2+de2i2-defi2+e2fi2-2bchi2-2cdhi2+2behi2+2cehi2+2e2hi2-2bghi2-2cghi2-2dghi2-eghi2-3fghi2-2g2hi2-bh2i2-ch2i2-dh2i2-fh2i2-3gh2i2-h3i2+bci3+cdi3-bei3-cei3-e2i3-egi3+fgi3+3bhi3+3chi3+3dhi3+5ehi3+3fhi3+ghi3-bi4-ci4-di4-2ei4-fi4-gi4+3hi4-i5 bcdef2-bcdefg+cdef2g-cdefgh+def2gh-cdef2i+cdefgi-def2gi+bcdehi-bcdfhi-def2hi+bcdghi+cdeghi+befghi+cefghi+3defghi+e2fghi-bf2ghi-cf2ghi-df2ghi-ef2ghi-f3ghi+2efg2hi-f2g2hi+2efgh2i-2f2gh2i+fg2h2i-bcdei2+bcdfi2+def2i2-defgi2+ef2gi2-2bcdhi2-2cdehi2+2bcfhi2+2cdfhi2+2ef2hi2-2bcghi2-2cdghi2-2deghi2-3efghi2+f2ghi2-2fg2hi2-bch2i2-cdh2i2-deh2i2+bfh2i2+cfh2i2+dfh2i2+f2h2i2-2bgh2i2-2cgh2i2-2dgh2i2-2egh2i2-2fgh2i2-3g2h2i2+fh3i2-3gh3i2+bcdi3+cdei3-bcfi3-cdfi3-ef2i3+efgi3-f2gi3+3bchi3+3cdhi3+3dehi3-3bfhi3-3cfhi3-3dfhi3-3f2hi3+3bghi3+3cghi3+3dghi3+3eghi3+3fghi3+3g2hi3+3bh2i3+3ch2i3+3dh2i3+3eh2i3+3fh2i3+3gh2i3+2h3i3-bci4-cdi4-dei4+bfi4+cfi4+dfi4+f2i4-4bhi4-4chi4-4dhi4-4ehi4-7fhi4-ghi4+2h2i4+bi5+ci5+di5+ei5+2fi5+gi5-4hi5+i6 bcdefg2-bcdefgh+cdefg2h-cdefg2i+bcdefhi+bcdfghi+bcefghi+bdefghi+4cdefghi+d2efghi+2de2fghi+2def2ghi+e2f2ghi-bcdg2hi-cdeg2hi-bcfg2hi-cdfg2hi-befg2hi-cefg2hi-2defg2hi-e2fg2hi-2efg3hi-f2g3hi+2defgh2i+f2g2h2i-2fg3h2i-bcdefi2+bcdegi2+defg2i2-2bcdehi2-2cdefhi2-2bcfghi2-2cdfghi2-2befghi2-2cefghi2-5defghi2-2e2fghi2-4ef2ghi2+2bcg2hi2+2cdg2hi2+2deg2hi2+2bfg2hi2+2cfg2hi2+2dfg2hi2+efg2hi2+4fg3hi2-bcdh2i2-cdeh2i2-defh2i2-bcgh2i2-cdgh2i2-degh2i2-2bfgh2i2-2cfgh2i2-2dfgh2i2-6efgh2i2-2f2gh2i2+bg2h2i2+cg2h2i2+dg2h2i2+eg2h2i2-2fg2h2i2+2g3h2i2-3fgh3i2+bcdei3+cdefi3-bcdgi3-cdegi3-efg2i3+3bcdhi3+3cdehi3+3defhi3+3bfghi3+3cfghi3+3dfghi3+4efghi3+3f2ghi3-3bg2hi3-3cg2hi3-3dg2hi3-3eg2hi3+2fg2hi3-3g3hi3+3bch2i3+3cdh2i3+3deh2i3+3efh2i3+3bgh2i3+3cgh2i3+3dgh2i3+3egh2i3+6fgh2i3+3g2h2i3+bh3i3+ch3i3+dh3i3+eh3i3+fh3i3+5gh3i3+h4i3-bcdi4-cdei4-defi4+bcgi4+cdgi4+degi4+fg2i4-4bchi4-4cdhi4-4dehi4-4efhi4-fghi4-3g2hi4-6bh2i4-6ch2i4-6dh2i4-6eh2i4-6fh2i4-4gh2i4-2h3i4+bci5+cdi5+dei5+efi5-bgi5-cgi5-dgi5-egi5-g2i5+5bhi5+5chi5+5dhi5+5ehi5+5fhi5+5ghi5-5h2i5-bi6-ci6-di6-ei6-fi6-2gi6+5hi6-i7 bcdefgh2+5bcdefghi+c2defghi+2cd2efghi+2cde2fghi+d2e2fghi+2cdef2ghi+2de2f2ghi+2cdefg2hi+2def2g2hi+e2f2g2hi-bcdefh2i-bcdegh2i-bcdfgh2i-bcefgh2i-bdefgh2i-3cdefgh2i-d2efgh2i-2de2fgh2i-2def2gh2i-e2f2gh2i-2defgh3i-2efg2h3i-f2g2h3i-bcdefgi2-bcdefhi2-2bcdeghi2-2bcdfghi2-2bcefghi2-2bdefghi2-8cdefghi2-2d2efghi2-4de2fghi2-4def2ghi2-2e2f2ghi2-4defg2hi2-4ef2g2hi2+bcdeh2i2+cdefh2i2-2defgh2i2-bcg2h2i2-cdg2h2i2-deg2h2i2-2bfg2h2i2-2cfg2h2i2-2dfg2h2i2-5efg2h2i2-3f2g2h2i2-3fg3h2i2+bcdh3i2+cdeh3i2+defh3i2+2bcgh3i2+2cdgh3i2+2degh3i2+2bfgh3i2+2cfgh3i2+2dfgh3i2+4efgh3i2+2f2gh3i2+bg2h3i2+cg2h3i2+dg2h3i2+eg2h3i2+fg2h3i2+3fgh4i2+3g2h4i2+bcdefi3+cdefgi3+2bcdehi3+2cdefhi3+3bcdghi3+3cdeghi3+3bcfghi3+3cdfghi3+3befghi3+3cefghi3+9defghi3+3e2fghi3+6ef2ghi3+6efg2hi3+3f2g2hi3+3bcgh2i3+3cdgh2i3+3degh2i3+3bfgh2i3+3cfgh2i3+3dfgh2i3+8efgh2i3+3f2gh2i3+3bg2h2i3+3cg2h2i3+3dg2h2i3+3eg2h2i3+9fg2h2i3+3g3h2i3-2bch3i3-2cdh3i3-2deh3i3-2efh3i3-3bgh3i3-3cgh3i3-3dgh3i3-3egh3i3+fgh3i3+3g2h3i3-bh4i3-ch4i3-dh4i3-eh4i3-fh4i3-3gh4i3-h5i3-bcdei4-cdefi4-defgi4-3bcdhi4-3cdehi4-3defhi4-4bcghi4-4cdghi4-4deghi4-4bfghi4-4cfghi4-4dfghi4-8efghi4-4f2ghi4-8fg2hi4-2bch2i4-2cdh2i4-2deh2i4-2efh2i4-8bgh2i4-8cgh2i4-8dgh2i4-8egh2i4-9fgh2i4-6g2h2i4+2bh3i4+2ch3i4+2dh3i4+2eh3i4+2fh3i4-8gh3i4-h4i4+bcdi5+cdei5+defi5+efgi5+4bchi5+4cdhi5+4dehi5+4efhi5+5bghi5+5cghi5+5dghi5+5eghi5+5fghi5+5g2hi5+5bh2i5+5ch2i5+5dh2i5+5eh2i5+5fh2i5-gh2i5+5h3i5-bci6-cdi6-dei6-efi6-fgi6-5bhi6-5chi6-5dhi6-5ehi6-5fhi6+4h2i6+bi7+ci7+di7+ei7+fi7+gi7-5hi7+i8 bcdefghi2+17c2defghi2+34cd2efghi2+34cde2fghi2+17d2e2fghi2+34cdef2ghi2+34de2f2ghi2+34cdefg2hi2+34def2g2hi2+17e2f2g2hi2+34cdefgh2i2+34defg2h2i2+34ef2g2h2i2-17bcdefgi3-34bcdefhi3-34bcdeghi3-34bcdfghi3-34bcefghi3-34bdefghi3+49cdefghi3-34d2efghi3+33de2fghi3+33def2ghi3-34e2f2ghi3+33defg2hi3+33ef2g2hi3-17bcdeh2i3-17cdefh2i3-34bcdgh2i3-34cdegh2i3-34bcfgh2i3-34cdfgh2i3-34befgh2i3-34cefgh2i3+49defgh2i3-34e2fgh2i3+33ef2gh2i3-17bcg2h2i3-17cdg2h2i3-17deg2h2i3-34bfg2h2i3-34cfg2h2i3-34dfg2h2i3+49efg2h2i3+16f2g2h2i3+50fg3h2i3+50efgh3i3-fg2h3i3-17g3h3i3+17bcdefi4+17cdefgi4-50bcdehi4-50cdefhi4-50bcdghi4-50cdeghi4-50bcfghi4-50cdfghi4-50befghi4-50cefghi4-32defghi4-50e2fghi4+ef2ghi4+efg2hi4-50f2g2hi4-50bcdh2i4-50cdeh2i4-50defh2i4+bcgh2i4+cdgh2i4+degh2i4+bfgh2i4+cfgh2i4+dfgh2i4-48efgh2i4+f2gh2i4-50bg2h2i4-50cg2h2i4-50dg2h2i4-50eg2h2i4-48fg2h2i4-50g3h2i4+17bch3i4+17cdh3i4+17deh3i4+17efh3i4-50bgh3i4-50cgh3i4-50dgh3i4-50egh3i4-32fgh3i4-49g2h3i4-33gh4i4-17bcdei5-17cdefi5-17defgi5+33bcdhi5+33cdehi5+33defhi5+33bcghi5+33cdghi5+33deghi5+33bfghi5+33cfghi5+33dfghi5+49efghi5+33f2ghi5-35fg2hi5-bch2i5-cdh2i5-deh2i5-efh2i5-2bgh2i5-2cgh2i5-2dgh2i5-2egh2i5-36fgh2i5+32g2h2i5+33bh3i5+33ch3i5+33dh3i5+33eh3i5+33fh3i5+32gh3i5+50h4i5+17bcdi6+17cdei6+17defi6+17efgi6-16bchi6-16cdhi6-16dehi6-16efhi6-16bghi6-16cghi6-16dghi6-16eghi6+fghi6-16g2hi6-32bh2i6-32ch2i6-32dh2i6-32eh2i6-32fh2i6-17bci7-17cdi7-17dei7-17efi7-17fgi7-bhi7-chi7-dhi7-ehi7-fhi7-17ghi7-49h2i7+17bi8+17ci8+17di8+17ei8+17fi8+17gi8-hi8+17i9-17j9 mathicgb-master/examples/module.ideal000077500000000000000000000001611311555162500202350ustar00rootroot00000000000000101 4 1 1 1 1 1 4 a<1>+b<2>+c<1>+d<1> ab<1>+bc<1>+cd<1>+da<1> abc<1>+bcd<1>+cda<1>+dab<1> abcd<1>-1<1> mathicgb-master/examples/tiny.ideal000077500000000000000000000000361311555162500177340ustar00rootroot00000000000000101 4 1 1 1 1 1 2 a2d-b a3-c mathicgb-master/examples/yang1.ideal000077500000000000000000000100531311555162500177700ustar00rootroot00000000000000101 48 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 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 66 uS+vT+wU+xV qS+rT+sU+tV mS+nT+oU+pV iS+jT+kU+lV eS+fT+gU+hV aS+bT+cU+dV uO+vP+wQ+xR qO+rP+sQ+tR mO+nP+oQ+pR iO+jP+kQ+lR eO+fP+gQ+hR aO+bP+cQ+dR uK+vL+wM+xN qK+rL+sM+tN mK+nL+oM+pN iK+jL+kM+lN eK+fL+gM+hN aK+bL+cM+dN uG+vH+wI+xJ qG+rH+sI+tJ mG+nH+oI+pJ iG+jH+kI+lJ eG+fH+gI+hJ aG+bH+cI+dJ uC+vD+wE+xF qC+rD+sE+tF mC+nD+oE+pF iC+jD+kE+lF eC+fD+gE+hF aC+bD+cE+dF uy+vz+wA+xB qy+rz+sA+tB my+nz+oA+pB iy+jz+kA+lB ey+fz+gA+hB ay+bz+cA+dB JMPS-INPS-JLQS+HNQS+ILRS-HMRS-JMOT+INOT+JKQT-GNQT-IKRT+GMRT+JLOU-HNOU-JKPU+GNPU+HKRU-GLRU-ILOV+HMOV+IKPV-GMPV-HKQV+GLQV FMPS-ENPS-FLQS+DNQS+ELRS-DMRS-FMOT+ENOT+FKQT-CNQT-EKRT+CMRT+FLOU-DNOU-FKPU+CNPU+DKRU-CLRU-ELOV+DMOV+EKPV-CMPV-DKQV+CLQV BMPS-ANPS-BLQS+zNQS+ALRS-zMRS-BMOT+ANOT+BKQT-yNQT-AKRT+yMRT+BLOU-zNOU-BKPU+yNPU+zKRU-yLRU-ALOV+zMOV+AKPV-yMPV-zKQV+yLQV FIPS-EJPS-FHQS+DJQS+EHRS-DIRS-FIOT+EJOT+FGQT-CJQT-EGRT+CIRT+FHOU-DJOU-FGPU+CJPU+DGRU-CHRU-EHOV+DIOV+EGPV-CIPV-DGQV+CHQV BIPS-AJPS-BHQS+zJQS+AHRS-zIRS-BIOT+AJOT+BGQT-yJQT-AGRT+yIRT+BHOU-zJOU-BGPU+yJPU+zGRU-yHRU-AHOV+zIOV+AGPV-yIPV-zGQV+yHQV BEPS-AFPS-BDQS+zFQS+ADRS-zERS-BEOT+AFOT+BCQT-yFQT-ACRT+yERT+BDOU-zFOU-BCPU+yFPU+zCRU-yDRU-ADOV+zEOV+ACPV-yEPV-zCQV+yDQV FILS-EJLS-FHMS+DJMS+EHNS-DINS-FIKT+EJKT+FGMT-CJMT-EGNT+CINT+FHKU-DJKU-FGLU+CJLU+DGNU-CHNU-EHKV+DIKV+EGLV-CILV-DGMV+CHMV BILS-AJLS-BHMS+zJMS+AHNS-zINS-BIKT+AJKT+BGMT-yJMT-AGNT+yINT+BHKU-zJKU-BGLU+yJLU+zGNU-yHNU-AHKV+zIKV+AGLV-yILV-zGMV+yHMV BELS-AFLS-BDMS+zFMS+ADNS-zENS-BEKT+AFKT+BCMT-yFMT-ACNT+yENT+BDKU-zFKU-BCLU+yFLU+zCNU-yDNU-ADKV+zEKV+ACLV-yELV-zCMV+yDMV BEHS-AFHS-BDIS+zFIS+ADJS-zEJS-BEGT+AFGT+BCIT-yFIT-ACJT+yEJT+BDGU-zFGU-BCHU+yFHU+zCJU-yDJU-ADGV+zEGV+ACHV-yEHV-zCIV+yDIV FILO-EJLO-FHMO+DJMO+EHNO-DINO-FIKP+EJKP+FGMP-CJMP-EGNP+CINP+FHKQ-DJKQ-FGLQ+CJLQ+DGNQ-CHNQ-EHKR+DIKR+EGLR-CILR-DGMR+CHMR BILO-AJLO-BHMO+zJMO+AHNO-zINO-BIKP+AJKP+BGMP-yJMP-AGNP+yINP+BHKQ-zJKQ-BGLQ+yJLQ+zGNQ-yHNQ-AHKR+zIKR+AGLR-yILR-zGMR+yHMR BELO-AFLO-BDMO+zFMO+ADNO-zENO-BEKP+AFKP+BCMP-yFMP-ACNP+yENP+BDKQ-zFKQ-BCLQ+yFLQ+zCNQ-yDNQ-ADKR+zEKR+ACLR-yELR-zCMR+yDMR BEHO-AFHO-BDIO+zFIO+ADJO-zEJO-BEGP+AFGP+BCIP-yFIP-ACJP+yEJP+BDGQ-zFGQ-BCHQ+yFHQ+zCJQ-yDJQ-ADGR+zEGR+ACHR-yEHR-zCIR+yDIR BEHK-AFHK-BDIK+zFIK+ADJK-zEJK-BEGL+AFGL+BCIL-yFIL-ACJL+yEJL+BDGM-zFGM-BCHM+yFHM+zCJM-yDJM-ADGN+zEGN+ACHN-yEHN-zCIN+yDIN loru-kpru-lnsu+jpsu+kntu-jotu-loqv+kpqv+lmsv-ipsv-kmtv+iotv+lnqw-jpqw-lmrw+iprw+jmtw-intw-knqx+joqx+kmrx-iorx-jmsx+insx horu-gpru-hnsu+fpsu+gntu-fotu-hoqv+gpqv+hmsv-epsv-gmtv+eotv+hnqw-fpqw-hmrw+eprw+fmtw-entw-gnqx+foqx+gmrx-eorx-fmsx+ensx doru-cpru-dnsu+bpsu+cntu-botu-doqv+cpqv+dmsv-apsv-cmtv+aotv+dnqw-bpqw-dmrw+aprw+bmtw-antw-cnqx+boqx+cmrx-aorx-bmsx+ansx hkru-glru-hjsu+flsu+gjtu-fktu-hkqv+glqv+hisv-elsv-gitv+ektv+hjqw-flqw-hirw+elrw+fitw-ejtw-gjqx+fkqx+girx-ekrx-fisx+ejsx dkru-clru-djsu+blsu+cjtu-bktu-dkqv+clqv+disv-alsv-citv+aktv+djqw-blqw-dirw+alrw+bitw-ajtw-cjqx+bkqx+cirx-akrx-bisx+ajsx dgru-chru-dfsu+bhsu+cftu-bgtu-dgqv+chqv+desv-ahsv-cetv+agtv+dfqw-bhqw-derw+ahrw+betw-aftw-cfqx+bgqx+cerx-agrx-besx+afsx hknu-glnu-hjou+flou+gjpu-fkpu-hkmv+glmv+hiov-elov-gipv+ekpv+hjmw-flmw-hinw+elnw+fipw-ejpw-gjmx+fkmx+ginx-eknx-fiox+ejox dknu-clnu-djou+blou+cjpu-bkpu-dkmv+clmv+diov-alov-cipv+akpv+djmw-blmw-dinw+alnw+bipw-ajpw-cjmx+bkmx+cinx-aknx-biox+ajox dgnu-chnu-dfou+bhou+cfpu-bgpu-dgmv+chmv+deov-ahov-cepv+agpv+dfmw-bhmw-denw+ahnw+bepw-afpw-cfmx+bgmx+cenx-agnx-beox+afox dgju-chju-dfku+bhku+cflu-bglu-dgiv+chiv+dekv-ahkv-celv+aglv+dfiw-bhiw-dejw+ahjw+belw-aflw-cfix+bgix+cejx-agjx-bekx+afkx hknq-glnq-hjoq+floq+gjpq-fkpq-hkmr+glmr+hior-elor-gipr+ekpr+hjms-flms-hins+elns+fips-ejps-gjmt+fkmt+gint-eknt-fiot+ejot dknq-clnq-djoq+bloq+cjpq-bkpq-dkmr+clmr+dior-alor-cipr+akpr+djms-blms-dins+alns+bips-ajps-cjmt+bkmt+cint-aknt-biot+ajot dgnq-chnq-dfoq+bhoq+cfpq-bgpq-dgmr+chmr+deor-ahor-cepr+agpr+dfms-bhms-dens+ahns+beps-afps-cfmt+bgmt+cent-agnt-beot+afot dgjq-chjq-dfkq+bhkq+cflq-bglq-dgir+chir+dekr-ahkr-celr+aglr+dfis-bhis-dejs+ahjs+bels-afls-cfit+bgit+cejt-agjt-bekt+afkt dgjm-chjm-dfkm+bhkm+cflm-bglm-dgin+chin+dekn-ahkn-celn+agln+dfio-bhio-dejo+ahjo+belo-aflo-cfip+bgip+cejp-agjp-bekp+afkpmathicgb-master/fixspace000066400000000000000000000042771311555162500156700ustar00rootroot00000000000000#!/bin/bash # Does the following operations on the files passed as arguments: # - Remove trailing space from lines # - Remove trailing blank lines # - Remove/convert DOS-style line breaks # - Expand tabs to spaces with a tabspace of 8 # I once had an error where the conversion had an error (the computer # didn't have dos2unix), resulting in the converted files being empty. # The result was that every file got replaced by an empty file! That # was not so nice, so this script stops operation as soon as any error # occurs, and it also checks that only space has been changed before # it overwrites the original file with a space-fixed version. for f in $*; do echo $f; tr -d '\r' < $f > __spaceTmp0; if [ $? != 0 ]; then echo "There was an error removing DOS-style line breaks."; exit 1; fi; expand -4 < __spaceTmp0 > __spaceTmp1; if [ $? != 0 ]; then echo "There was an error expanding tabs."; exit 1; fi; sed 's/[[:blank:]]*$//g' < __spaceTmp1 > __spaceTmp2; if [ $? != 0 ]; then echo "There was an error eliminating trailing space from lines."; exit 1; fi; # Make completely sure that we only changed the spaces diff -EbwB -q $f __spaceTmp2; if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi; sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' < __spaceTmp2 > __spaceTmp3; if [ $? != 0 ]; then echo "There was an error eliminating trailing blank lines."; exit 1; fi; # We have to do diff twice, because diff will not ignore trailing # lines that consist only of spaces. It will ignore changes to space and removal of # completely empty lines, so if we do it twice we get the right thing. # Make completely sure that we only changed the spaces diff -EbwB -q __spaceTmp2 __spaceTmp3; if [ $? != 0 ]; then echo "There was an error. Conversion not confirmed correct."; exit 1; fi; diff -q $f __spaceTmp3 1>/dev/null; if [ $? != 0 ]; then mv -f __spaceTmp3 $f; if [ $? != 0 ]; then echo "There was an error moving fixed file into place."; exit 1; fi; echo "Fixed space issue for $f." fi rm -f __spaceTmp0 __spaceTmp1 __spaceTmp2 __spaceTmp3; if [ $? != 0 ]; then echo "There was an error removing temporary files."; exit 1; fi; done; mathicgb-master/gpl-2.0.txt000066400000000000000000000432541311555162500157610ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey 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 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. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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. mathicgb-master/gpl-3.0.txt000066400000000000000000001045131311555162500157560ustar00rootroot00000000000000 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 . mathicgb-master/libs/000077500000000000000000000000001311555162500150625ustar00rootroot00000000000000mathicgb-master/libs/.gitignore000066400000000000000000000000071311555162500170470ustar00rootroot00000000000000gtest/ mathicgb-master/replace000077500000000000000000000003321311555162500154700ustar00rootroot00000000000000#!/bin/bash echo "Running script \"sed s/$1/$2/\"" for i in 1 2 3; do /usr/bin/sleep 1; echo -n .; done for f in `ls src/*.cpp src/*.h`; do echo "Processing $f"; sed "s/$1/$2/" < $f > $f.tmp mv $f.tmp $f done mathicgb-master/src/000077500000000000000000000000001311555162500147205ustar00rootroot00000000000000mathicgb-master/src/checksource/000077500000000000000000000000001311555162500172165ustar00rootroot00000000000000mathicgb-master/src/checksource/CheckSource.cpp000077500000000000000000000115741311555162500221330ustar00rootroot00000000000000// Program for checking format of code, with respect to proper // copyright header, no tabs, order of includes and so on. // // This code is not pretty, especially not the duplication of Scanner, // but this makes this whole thing easy to compile and this is VERY // quick-and-dirty code anyway. Anyone who wants to clean up thing up // with proper integration into the build system is more than welcome // to do so. #include "Scanner.cpp" #include #include #include #include #include void error(std::string str) { throw std::runtime_error(str); } bool endsWith(const std::string& a, const std::string& b) { return a.size() >= b.size() && a.substr(a.size() - b.size()) == b; } bool matchInclude(Scanner& in, bool& system) { if (!in.match("#include ")) return false; char delim = '\"'; system = false; if (!in.match('\"')) { if (in.match('<')) { system = true; delim = '>'; } else in.reportError("Expected < or \" after #include."); } in.readUntil(delim); in.expect(delim); return true; } std::string stripEnding(const std::string& str) { const auto index = str.find_last_of('.'); if (index == std::string::npos) return str; else return str.substr(0, index); } void checkCopyrightHeader(Scanner& in) { const char* const l1 = "// MathicGB copyright 2012 all rights reserved. " "MathicGB comes with ABSOLUTELY\n"; const char* const l2 = "// NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt.\n"; in.expect(l1); in.expect(l2); } void checkStdInc(Scanner& in) { in.eatWhite(); if (!in.match("#include \"mathicgb/stdinc.h\"\n")) in.expect("#include \"stdinc.h\"\n"); } void checkIncludes(Scanner& in) { bool sawSystem = false; bool system; while (matchInclude(in, system)) { if (sawSystem && !system) in.reportError("#include < > must come after all #include \" \"."); sawSystem = system; } } void checkInclusionGuard(Scanner& in, const std::string& filename) { auto normalize = [](const std::string& str) { std::string norm; for (size_t i = 0; i < str.size(); ++i) if (str[i] != '_') norm += std::toupper(str[i]); return norm; }; in.expect("#ifndef "); const auto macroName = in.readString(); const auto fileNorm = normalize ("MATHICGB_" + stripEnding(filename) + "_GUARD"); if (fileNorm != normalize(macroName)) { std::ostringstream err; err << "Inclusion guard name does not match file name.\n"; err << "Normalization removes _ and converts to upper case.\n"; err << " Filename normalizes to: " << fileNorm << '\n'; err << "macro name normalizes to: " << normalize(macroName) << '\n'; in.reportError(err.str()); } in.expect("#define "); std::string macro2; macro2 = in.readString(); if (macroName != macro2) { std::ostringstream out; out << "Inclusion guard #ifndef and #define macro name mismatch.\n"; out << "#ifndef macro name: " << macroName << '\n'; out << "#define macro name: " << macro2 << '\n'; in.reportError(out.str()); } } void checkOther(const std::string& filename) { std::ifstream file(filename.c_str(), std::ios_base::binary); file.peek(); if (!file) error("could not open file"); Scanner in(file); bool mgbNamespace = false; while (!in.matchEOF()) { if (in.peek() == '\r') in.reportError("File contains dos/windows line ending character \\r."); if (in.peek() == '\t') in.reportError("File contains a tab."); if ( in.match("Local Variables:") || in.match("compile-command:") || in.match("indent-tabs-mode:") ) in.reportError("File contains emacs-specific command comments."); if (in.match("namespace mgb") || in.match("MATHICGB_NAMESPACE_BEGIN")) mgbNamespace = true; else in.get(); } if (!mgbNamespace) in.reportError("MATHICGB_NAMESPACE_BEGIN does not appear in file"); } void checkFile(std::string filename) { try { std::cout << "Checking file " << filename << std::endl; const bool hpp = endsWith(filename, ".hpp"); const bool cpp = endsWith(filename, ".cpp"); if (!hpp && !cpp) return; checkOther(filename); std::ifstream file(filename.c_str()); if (!file) error("could not open file"); Scanner in(file); if (in.peekWhite()) in.reportError ("File should start with copyright header, not whitespace."); checkCopyrightHeader(in); if (in.peekWhite()) in.reportError ("There should not be whitespace after the copyright header."); if (cpp) checkStdInc(in); else checkInclusionGuard(in, filename); checkIncludes(in); } catch (std::exception& e) { std::cout << "*** ERROR in file " << filename << " ***\n" << e.what() << std::endl; } } int main(int argc, char* argv[]) { for (int i = 1; i < argc; ++i) checkFile(argv[i]); return 0; } mathicgb-master/src/checksource/Scanner.cpp000077500000000000000000000100031311555162500213100ustar00rootroot00000000000000#include "Scanner.hpp" #include #include #include #include static const size_t BufferSize = 10 * 1024; void reportSyntaxError(std::string s, uint64 lineNumber) { std::ostringstream out; out << "Syntax error on line " << lineNumber << ": " << s; throw std::runtime_error(out.str()); } void Scanner::reportError(std::string msg) const { reportSyntaxError(msg, lineCount()); } Scanner::Scanner(FILE* input): mFile(input), mStream(0), mLineCount(1), mChar(' '), mBuffer(BufferSize), mBufferPos(mBuffer.end()) { get(); } Scanner::Scanner(std::istream& input): mFile(0), mStream(&input), mLineCount(1), mChar(' '), mBuffer(BufferSize), mBufferPos(mBuffer.end()) { get(); } Scanner::Scanner(const char* const input): mFile(0), mStream(0), mLineCount(1), mChar(' '), mBuffer(input, input + std::strlen(input)), mBufferPos(mBuffer.begin()) { get(); } Scanner::Scanner(const std::string& input): mFile(0), mStream(0), mLineCount(1), mChar(' '), mBuffer(input.begin(), input.end()), mBufferPos(mBuffer.begin()) { get(); } bool Scanner::match(const char* const str) { eatWhite(); const auto size = std::strlen(str); if (!ensureBuffer(size)) return false; if (size == 0) return true; if (peek() != *str) return false; if (std::strncmp(&*mBufferPos, str + 1, size - 1) != 0) return false; ignore(size); return true; } bool Scanner::ensureBuffer(size_t min) { const auto got = std::distance(mBufferPos, mBuffer.end()) + 1; return got >= min || readBuffer(min - got); } void Scanner::expect(const char* str) { eatWhite(); const char* it = str; while (*it != '\0') { int character = get(); if (*it == character) { ++it; continue; } // Read the rest of what is there to improve error message. // TODO: read at least one char in total even if not alnum. std::ostringstream got; if (character == EOF && it == str) got << "no more input"; else { got << '\"' << std::string(str, it); if (isalnum(character)) got << static_cast(character); while (isalnum(peek())) got << static_cast(get()); got << '\"'; } reportErrorUnexpectedToken(str, got.str()); } } void Scanner::expectEOF() { eatWhite(); if (get() != EOF) reportErrorUnexpectedToken("no more input", ""); } void Scanner::errorExpectTwo(char a, char b, int got) { std::ostringstream err; err << '\'' << a << "' or '" << b << '\''; reportErrorUnexpectedToken(err.str(), got); } void Scanner::errorExpectOne(char expected, int got) { std::ostringstream err; err << '\'' << expected << '\''; reportErrorUnexpectedToken(err.str(), got); } void Scanner::reportErrorUnexpectedToken(const std::string& expected, int got) { std::ostringstream gotDescription; if (got == EOF) gotDescription << "no more input"; else gotDescription << '\'' << static_cast(got) << '\''; reportErrorUnexpectedToken(expected, gotDescription.str()); } void Scanner::reportErrorUnexpectedToken( const std::string& expected, const std::string& got ) { std::ostringstream errorMsg; errorMsg << "Expected " << expected; if (got != "") errorMsg << ", but got " << got; errorMsg << '.'; reportError(errorMsg.str()); } bool Scanner::readBuffer(size_t minRead) { auto saveCount = std::distance(mBufferPos, mBuffer.end()); if (mBufferPos != mBuffer.begin() && mBufferPos != mBuffer.end()) std::copy(mBufferPos, mBuffer.end(), mBuffer.begin()); mBuffer.resize(std::max(saveCount + minRead, mBuffer.capacity())); auto readInto = reinterpret_cast(mBuffer.data() + saveCount); auto readCount = mBuffer.size() - saveCount; size_t didReadCount = 0; if (mFile != 0) { didReadCount = fread(readInto, 1, readCount, mFile); } else if (mStream != 0) { mStream->read(readInto, readCount); didReadCount = mStream->gcount(); } mBuffer.resize(saveCount + didReadCount); mBufferPos = mBuffer.begin(); return didReadCount >= minRead; } mathicgb-master/src/checksource/Scanner.hpp000077500000000000000000000155031311555162500213270ustar00rootroot00000000000000#ifndef MATHICGB_SCANNER_GUARD #define MATHICGB_SCANNER_GUARD #include #include #include #include #include #include #include typedef unsigned long long uint64; /// This class offers an input interface which is more convenient and /// often more efficient than dealing with a FILE* or std::istream /// directly. It keeps track of the current line number to report /// better error messages. Only one Scanner should be reading from a /// given FILE* or std::istream due to buffering and line number counting. /// /// All input methods whose documentation does not specifically say /// otherwise skip whitespace. /// /// There are four concepts for consuming input through a Scanner: /// /// Read X: Require an X to be in the input, and return what is read. /// /// Expect X: Require the exact value X to be in the input and skip past it. /// /// Match X: Return true if the exact value X is in the input, and in that case /// skip past it. Otherwise return false and do nothing else. /// /// MatchRead X: Return true of an X is in the input. In that case, /// read the X into a reference parameter and return true. /// /// Peek X: Return true if X is the next thing int he input. Do not skip /// past anything. May or may not skip whitespace depending on what X is. /// /// If a requirement is not met, Scanner reports a syntax error. class Scanner { public: /// Construct a Scanner object reading from the input FILE*. Scanner(FILE* input); /// Construct a Scanner object reading from the input std::istream. Scanner(std::istream& input); /// Construct a Scanner object reading from the input string. Scanner(const char* const input); /// Construct a Scanner object reading from the input string. Scanner(const std::string& input); /// Reads a single character from the stream. int get(); /// Takes count characters off the stream. void ignore(size_t count); /// Return true if the next character is c, and in that case skip /// past it. bool match(char c); /// Return true if no more input. bool matchEOF(); bool match(const char* const str); /// Require the next character to be equal to expected. This /// character is skipped past. void expect(char expected); /// Require the next character to be equal to a or b. This character /// is skipped past. void expect(char a, char b); /// Require the following characters to be equal to str. These /// characters are skipped past. void expect(const char* str); /// Require the following characters to be equal to str. These /// characters are skipped past. void expect(const std::string& str) {expect(str.c_str());} /// Require that there is no more input. void expectEOF(); /// Reads a T. T must be an integer type with a std::numeric_limits /// specialization. Negative numbers are allows if T is signed. template T readInteger(bool negate = false); /// Reads a T if it is there. Does not recognize + or - as the start /// of an integer. template bool matchReadIntegerNoSign(T& t, bool negate = false); void readUntil(char delimiter) { while (peek() != delimiter && !matchEOF()) get(); } std::string readString() { std::string str; while (!peekWhite() && !matchEOF()) str += get(); return str; } /// Returns the next character or EOF. Does not skip whitespace. int peek() {return mChar;} /// Returns true if the next character is a digit. Does not skip /// whitespace. bool peekDigit() {return std::isdigit(peek());} bool peekAlpha() {return std::isalpha(peek());} /// Returns true if the next character is whitespace. Does not skip /// whitespace. Whitespace is defined by std::isspace(). bool peekWhite() {return isspace(peek());} /// Returns true if the next character is + or -. Does not skip /// whitespace. bool peekSign() {return peek() == '+' || peek() == '-';} /// Returns the number of newlines seen plus one. Does not skip /// whitespace. uint64 lineCount() const {return mLineCount;} /// Reads past any whitespace. inline void eatWhite(); void reportError(std::string msg) const; private: void errorExpectTwo(char a, char b, int got); void errorExpectOne(char expected, int got); void reportErrorUnexpectedToken(const std::string& expected, int got); void reportErrorUnexpectedToken (const std::string& expected, const std::string& got); bool ensureBuffer(size_t min); bool readBuffer(size_t minRead); FILE* mFile; std::istream* mStream; uint64 mLineCount; int mChar; // next character on stream std::vector mBuffer; std::vector::iterator mBufferPos; }; inline bool Scanner::matchEOF() { eatWhite(); return peek() == EOF; } inline bool Scanner::match(char c) { eatWhite(); if (c == peek()) { get(); return true; } else return false; } inline void Scanner::expect(char a, char b) { eatWhite(); int got = get(); if (got != a && got != b) errorExpectTwo(a, b, got); } inline void Scanner::expect(char expected) { eatWhite(); int got = get(); if (got != expected) errorExpectOne(expected, got); } inline void Scanner::eatWhite() { while (peekWhite()) get(); } inline int Scanner::get() { if (mChar == '\n') ++mLineCount; int oldChar = mChar; if (mBufferPos == mBuffer.end() && !readBuffer(1)) mChar = EOF; else { mChar = *mBufferPos; ++mBufferPos; } return oldChar; } inline void Scanner::ignore(size_t count) { for (size_t i = 0; i < count; ++i) get(); } template T Scanner::readInteger(const bool negate) { static_assert(std::numeric_limits::is_integer, ""); eatWhite(); const bool minus = !match('+') && match('-'); const bool positive = minus == negate; if (!peekDigit()) reportErrorUnexpectedToken("an integer", ""); // Skip leading zeroes and return if the number is zero. if (peek() == '0') { while (peek() == '0') get(); if (!peekDigit()) return static_cast(0); } // Checking this here allows us to recognize -0 as non-negative. if (!positive && !std::numeric_limits::is_signed) reportErrorUnexpectedToken("a positive integer", ""); const auto min = std::numeric_limits::min(); const auto max = std::numeric_limits::max(); auto t = static_cast(0); while (peekDigit()) { const auto c = static_cast(get()); const auto d = positive ? c - '0' : -(c - '0'); if (positive ? t > (max - d) / 10 : t < (min - d) / 10) { std::ostringstream err; err << "an integer in the range [" << min << ", " << max << ']'; reportErrorUnexpectedToken(err.str(), ""); } t = t * 10 + d; } return t; } template bool Scanner::matchReadIntegerNoSign(T& t, bool negate) { if (peekDigit()) { t = readInteger(negate); return true; } else return false; } #endif mathicgb-master/src/cli/000077500000000000000000000000001311555162500154675ustar00rootroot00000000000000mathicgb-master/src/cli/CommonParams.cpp000077500000000000000000000064051311555162500205770ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "CommonParams.hpp" #include "mathicgb/LogDomain.hpp" #include "mathicgb/LogDomainSet.hpp" MATHICGB_DEFINE_LOG_ALIAS("default", "F4Detail,SPairs"); MATHICGB_NAMESPACE_BEGIN CommonParams::CommonParams(size_t minDirectParams, size_t maxDirectParams): mTracingLevel("tracingLevel", "How much information to print out about what the program does. No " "information is shown if the value is zero. Higher values " "result in more information.", 0), mThreadCount("threadCount", "Specifies how many threads to use at a time. A value of 0 indicates that " "the program should choose the optimal number of threads.", 0), mLogs("log", "Enable the specified log. Do \"help logs\" to see all available logs and " "the details of how to configure what kind of logging you want. " "To enable logs X, Y and Z, do \"-log X,Y,Z\". " "To enabled all logs, do \"-log\" or \"-log all\".", "none"), mMinDirectParams(minDirectParams), mMaxDirectParams(maxDirectParams) { } void CommonParams::directOptions( std::vector tokens, mathic::CliParser& parser ) { if (tokens.size() < mMinDirectParams) mathic::reportError("Too few direct options"); if (tokens.size() > mMaxDirectParams) mathic::reportError("Too many direct options"); mDirectParameters = std::move(tokens); } void CommonParams::pushBackParameters( std::vector& parameters ) { parameters.push_back(&mLogs); parameters.push_back(&mTracingLevel); parameters.push_back(&mThreadCount); } void CommonParams::perform() { const std::string logs = mLogs.value().empty() ? "default" : mLogs.value(); LogDomainSet::singleton().performLogCommands(logs); tracingLevel = mTracingLevel.value(); // delete the old init object first to make the new one take control. mTbbInit.reset(); mTbbInit = make_unique( mThreadCount.value() == 0 ? mgb::mtbb::task_scheduler_init::automatic : mThreadCount.value() ); } void CommonParams::registerFileNameExtension(std::string extension) { MATHICGB_ASSERT(!extension.empty()); mExtensions.push_back(std::move(extension)); } size_t CommonParams::inputFileCount() const { return mDirectParameters.size(); } std::string CommonParams::inputFileName(size_t i) { MATHICGB_ASSERT(i < inputFileCount()); return mDirectParameters[i]; } std::string CommonParams::inputFileNameStem(size_t i) { MATHICGB_ASSERT(i < inputFileCount()); const auto& str = mDirectParameters[i]; const auto toStrip = inputFileNameExtension(i); MATHICGB_ASSERT (toStrip.size() < str.size() || (toStrip.empty() && str.empty())); return str.substr(0, str.size() - toStrip.size()); } std::string CommonParams::inputFileNameExtension(size_t i) { MATHICGB_ASSERT(i < inputFileCount()); const auto& str = mDirectParameters[i]; const auto end = mExtensions.end(); for (auto it = mExtensions.begin(); it != end; ++it) { if ( str.size() >= it->size() && str.substr(str.size() - it->size(), it->size()) == *it ) return *it; } return std::string(); } MATHICGB_NAMESPACE_END mathicgb-master/src/cli/CommonParams.hpp000077500000000000000000000034161311555162500206030ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_COMMON_PARAMS_GUARD #define MATHICGB_COMMON_PARAMS_GUARD #include "mathicgb/mtbb.hpp" #include #include MATHICGB_NAMESPACE_BEGIN class CommonParams { public: CommonParams(size_t minDirectParams, size_t maxDirectParams); void directOptions (std::vector tokens, mathic::CliParser& parser); void pushBackParameters(std::vector& parameters); /// Takes appropriate action depending on the parameters. For example this /// will set the number of threads in tbb. void perform(); /// If called with string X, then X will be considered an extension /// for a file name instead of part of the file name. void registerFileNameExtension(std::string extensions); /// Returns the number of direct parameters/input files. size_t inputFileCount() const; /// Returns the file name at offset i, if any. std::string inputFileName(size_t i); /// Returns the stem of the input file name at offset i, with any registered /// extensions stripped off. std::string inputFileNameStem(size_t i); /// Returns the registered extension of the input file name at offset i, /// if any. std::string inputFileNameExtension(size_t i); private: mathic::IntegerParameter mTracingLevel; mathic::IntegerParameter mThreadCount; mathic::StringParameter mLogs; std::vector mExtensions; /// to recognize file type /// to set thread count std::unique_ptr mTbbInit; std::size_t mMinDirectParams; std::size_t mMaxDirectParams; std::vector mDirectParameters; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/cli/GBAction.cpp000077500000000000000000000106741311555162500176340ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "GBAction.hpp" #include "mathicgb/ClassicGBAlg.hpp" #include "mathicgb/Basis.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/F4Reducer.hpp" #include "mathicgb/Scanner.hpp" #include "mathicgb/MathicIO.hpp" #include "mathicgb/Reducer.hpp" #include #include MATHICGB_NAMESPACE_BEGIN GBAction::GBAction(): mAutoTailReduce( "autoTailReduce", "Reduce the non-leading terms of all polynomials whenever an element " "is inserted into the basis. Only relevant to the " "classic Buchberger algorithm.", false), mAutoTopReduce( "autoTopReduce", "Reduce any basis element whose lead term becomes reducible " "by a different basis element. Only relevant to the " "classic Buchberger algorithm.", true), mSPairGroupSize( "sPairGroupSize", "Specifies how many S-pair to reduce at one time. A value of 0 " "indicates to use an appropriate default.", 0), mMinMatrixToStore( "storeMatrices", "If using a matrix-based reducer, store the matrices that are generated in " "files named X-1.mat, X-2.mat and so on where X is the project name. Only " "matrices with at least as many entries as the parameter are stored. " "A value of 0 indicates not to store any matrices.", 0), mModule( "module", "The input is a basis of a submodule over the polynomial ring instead of " "an ideal in the polynomial ring. This option is experimental.", false ), mParams(1, 1) {} void GBAction::directOptions( std::vector tokens, mic::CliParser& parser ) { mParams.directOptions(tokens, parser); } void GBAction::performAction() { mParams.perform(); mGBParams.perform(); const std::string projectName = mParams.inputFileNameStem(0); // read input const std::string inputBasisFile = projectName + ".ideal"; std::ifstream inputFile(inputBasisFile.c_str()); if (inputFile.fail()) mic::reportError("Could not read input file \"" + inputBasisFile + '\n'); Scanner in(inputFile); auto p = MathicIO<>().readRing(true, in); auto& ring = *p.first; auto basis = MathicIO<>().readBasis(ring, mModule.value(), in); // run algorithm const auto reducerType = Reducer::reducerType(mGBParams.mReducer.value()); std::unique_ptr reducer; if ( reducerType != Reducer::Reducer_F4_Old && reducerType != Reducer::Reducer_F4_New ) { reducer = Reducer::makeReducer(reducerType, ring); } else { auto f4Reducer = makeF4Reducer( ring, reducerType == Reducer::Reducer_F4_Old, mMinMatrixToStore.value() > 0 ? projectName : "", mMinMatrixToStore ); reducer = std::move(f4Reducer); } ClassicGBAlgParams params; params.reducer = reducer.get(); params.monoLookupType = mGBParams.mMonoLookup.value(); params.preferSparseReducers = mGBParams.mPreferSparseReducers.value(); params.sPairQueueType = mGBParams.mSPairQueue.value(); params.breakAfter = mGBParams.mBreakAfter.value(); params.printInterval = mGBParams.mPrintInterval.value(); params.sPairGroupSize = mSPairGroupSize.value(); params.reducerMemoryQuantum = mGBParams.mMemoryQuantum.value(); params.useAutoTopReduction = mAutoTopReduce.value(); params.useAutoTailReduction = mAutoTailReduce.value(); params.callback = nullptr; const auto gb = mModule.value() ? computeModuleGBClassicAlg(std::move(basis), params) : computeGBClassicAlg(std::move(basis), params); if (mGBParams.mOutputResult.value()) { std::ofstream out(projectName + ".gb"); MathicIO<>().writeBasis(gb, mModule.value(), out); } } const char* GBAction::staticName() { return "gb"; } const char* GBAction::name() const { return staticName(); } const char* GBAction::description() const { return "Compute a Grobner basis. " "The project name is an optional direct parameter."; } const char* GBAction::shortDescription() const { return "Compute a Grobner basis."; } void GBAction::pushBackParameters( std::vector& parameters ) { mParams.pushBackParameters(parameters); mGBParams.pushBackParameters(parameters); parameters.push_back(&mAutoTailReduce); parameters.push_back(&mAutoTopReduce); parameters.push_back(&mSPairGroupSize); parameters.push_back(&mMinMatrixToStore); parameters.push_back(&mModule); } MATHICGB_NAMESPACE_END mathicgb-master/src/cli/GBAction.hpp000077500000000000000000000022221311555162500176270ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_G_B_ACTION_GUARD #define MATHICGB_G_B_ACTION_GUARD #include "GBCommonParams.hpp" #include "CommonParams.hpp" #include MATHICGB_NAMESPACE_BEGIN /// Calculates a classic Grobner basis using Buchberger's algorithm class GBAction : public mathic::Action { public: GBAction(); virtual void directOptions( std::vector tokens, mic::CliParser& parser ); virtual void performAction(); static const char* staticName(); virtual const char* name() const; virtual const char* description() const; virtual const char* shortDescription() const; virtual void pushBackParameters(std::vector& parameters); private: CommonParams mParams; GBCommonParams mGBParams; mathic::BoolParameter mAutoTailReduce; mathic::BoolParameter mAutoTopReduce; //mic::IntegerParameter mTermOrder; mathic::IntegerParameter mSPairGroupSize; mathic::IntegerParameter mMinMatrixToStore; mic::BoolParameter mModule; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/cli/GBCommonParams.cpp000077500000000000000000000063111311555162500210040ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "GBCommonParams.hpp" #include "mathicgb/ModuleMonoSet.hpp" #include "mathicgb/MonoLookup.hpp" #include "mathicgb/Reducer.hpp" MATHICGB_NAMESPACE_BEGIN GBCommonParams::GBCommonParams(): mPreferSparseReducers( "preferSparseReducers", "If true, always use the sparsest reducer in polynomial reduction. " "This option impacts both classic and signature constrained " "polynomial reduction. Ties are broken by taking the oldest reducer. " "If this option is false, the oldest reducer is always used.", true ), mOutputResult( "outputResult", "If true, output the resulting Groebner or signature basis " "to the file .gb and in the signature basis " "case, the signatures of the syzygies are placed in .syz", false ), mSPairQueue( "spairQueue", "The priority queue used to order S-pairs.\n" " 0 tournament tree in front of triangle\n" " 1 heap in front of triangle\n" " 2 tournament tree\n" " 3 heap\n", 0 ), mBreakAfter( "breakAfter", "Stop the computation after this many elements have been added to " "the basis. The computation runs uninterrupted if the value is zero.", 0 ), mPrintInterval( "printInterval", "Print information about the computation every time this many S-pair " "reductions have been performed and at the end. Do not print information " "like this during the computation if the value is zero.", std::numeric_limits::max() ), mMonomialTable( "monomialTable", "The kind of monomial table data structure to use.\n", 2 ), mMonoLookup( "divisorLookup", "The monomial lookup data structure to use.\n", 2 ), mReducer( "reducer", "The data structure to use for polynomial reduction.\n", 4 ), mMemoryQuantum( "memoryQuantumForReducer", "Specifies how many items to allocate memory for at a time for the reducer.", 1024 * 1024) { { std::ostringstream reducerOut; Reducer::displayReducerTypes(reducerOut); mReducer.appendToDescription(reducerOut.str()); } { std::ostringstream out; out << "Monomial map data structures codes:\n"; MonoLookup::displayCodes(out); mMonoLookup.appendToDescription(out.str()); } { std::ostringstream out; out << "Module monomial set data structures codes:\n"; ModuleMonoSet::displayCodes(out); mMonomialTable.appendToDescription(out.str()); } } void GBCommonParams::pushBackParameters( std::vector& parameters ) { parameters.push_back(&mPreferSparseReducers); parameters.push_back(&mOutputResult); parameters.push_back(&mSPairQueue); parameters.push_back(&mBreakAfter); parameters.push_back(&mPrintInterval); parameters.push_back(&mMonomialTable); parameters.push_back(&mMonoLookup); parameters.push_back(&mReducer); parameters.push_back(&mMemoryQuantum); } void GBCommonParams::perform() { // currently there is nothing to do } MATHICGB_NAMESPACE_END mathicgb-master/src/cli/GBCommonParams.hpp000077500000000000000000000014761311555162500210200ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_GB_COMMON_PARAMS_GUARD #define MATHICGB_GB_COMMON_PARAMS_GUARD #include MATHICGB_NAMESPACE_BEGIN class GBCommonParams { public: GBCommonParams(); void pushBackParameters(std::vector& parameters); void perform(); mathic::BoolParameter mPreferSparseReducers; mathic::BoolParameter mOutputResult; mathic::IntegerParameter mSPairQueue; mathic::IntegerParameter mBreakAfter; mathic::IntegerParameter mPrintInterval; mathic::IntegerParameter mMonomialTable; mathic::IntegerParameter mMonoLookup; mathic::IntegerParameter mReducer; mathic::IntegerParameter mMemoryQuantum; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/cli/GBMain.cpp000077500000000000000000000026201311555162500172730ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "GBAction.hpp" #include "SigGBAction.hpp" #include "MatrixAction.hpp" #include "HelpAction.hpp" #include "mathicgb/LogDomainSet.hpp" #include #include #include #include // This is to satisfy the code checker that requires every file to contain // these macroes. MATHICGB_NAMESPACE_BEGIN MATHICGB_NAMESPACE_END int main(int argc, char **argv) { try { mathic::CliParser parser; parser.registerAction(); parser.registerAction(); parser.registerAction(); parser.registerAction(); std::vector commandLine(argv, argv + argc); commandLine.erase(commandLine.begin()); parser.parse(commandLine)->performAction(); } catch (const mathic::MathicException& e) { mathic::display(e.what()); return -1; } catch (std::exception& e) { mathic::display(e.what()); return -1; } catch (...) { std::cout << "UNKNOWN ERROR" << std::endl; // maybe there is some outer exception handler that might say something // reasonable about this exception, so rethrow the exception. throw; } mgb::LogDomainSet::singleton().printReport(std::cerr); return 0; }; mathicgb-master/src/cli/HelpAction.cpp000077500000000000000000000064111311555162500202260ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "HelpAction.hpp" #include "mathicgb/LogDomain.hpp" #include "mathicgb/LogDomainSet.hpp" #include MATHICGB_NAMESPACE_BEGIN void HelpAction::performAction() { if (topic() != "logs") { mathic::HelpAction::performAction(); return; } const char* header = "MathicGB offers a set of logs that can be enabled or disabled " "individually.\n" "\n" "A log can have a streaming component and a summary " "component. The streaming component is printed as the logged event " "occurs while the summary component is printed at the end. For example " "a log for opening files would stream a message every time a file is " "opened and it would report the total number of files opened when the " "program has run to the end. The summary can also include how long " "something took.\n" "\n" "An enabled log always prints its summary if it registered any events. " "The streaming component can be turned off even for an enabled log, and " "this is the default for some logs.\n" "\n" "You specify the log configuration using the option -log X, where X is " "a comma-seperated list of log specifications. Here is an example:\n" "\n" " A,+B,-C,D+,E-\n" "\n" "This enables logs A, B, D and E and disables C. Furthermore, streaming " "for D is turned on while it is turned off for E. The streaming setting " "for A, B and C is the default for those logs.\n" "\n" "A prefix of - disables the log while no prefix or a prefix of + enables " "it. A suffix of - turns off streaming while a suffix of + turns it on. " "If there is no suffix then the setting for streaming is unchanged. A " "prefix or suffix of 0 means do nothing.\n" "\n" "The following is a list of all compile-time enabled logs. The prefixes " "and suffixes indicate the default state of the log.\n"; mathic::display(header); auto& logs = LogDomainSet::singleton().logDomains(); for (auto it = logs.begin(); it != logs.end(); ++it) { const auto toSign = [](const bool b) {return b ? '+' : '-';}; std::cerr << "\n " << toSign((*it)->enabled()) << (*it)->name() << toSign((*it)->streamEnabledPure()) << '\n'; mathic::display((*it)->description(), " "); } const char* aliasDescription = "\nA log alias is a short-hand where one name stands for several log " "specifications. Prefixes and Suffixes also apply to aliases. If X " "expands to A+,-B,C then +X- expands to +A-,+B-,+C-. 0all- turns off " "all streaming output without enabling or disabling any logs.\n" "\n" "The following is a list of all aliases.\n"; mathic::display(aliasDescription); auto& aliases = LogDomainSet::singleton().aliases(); for (auto it = aliases.begin(); it != aliases.end(); ++it) { std::cerr << "\n " << it->first << " expands to\n"; std::string str = it->second; std::replace(str.begin(), str.end(), ',', ' '); mathic::display(str, " "); } std::cerr << "\n none expands to nothing\n" "\n" " all expands to all log names\n" "\n"; } MATHICGB_NAMESPACE_END mathicgb-master/src/cli/HelpAction.hpp000077500000000000000000000006061311555162500202330ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_HELP_ACTION_GUARD #define MATHICGB_HELP_ACTION_GUARD #include MATHICGB_NAMESPACE_BEGIN class HelpAction : public mathic::HelpAction { public: virtual void performAction(); }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/cli/MatrixAction.cpp000077500000000000000000000122031311555162500205760ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "MatrixAction.hpp" #include "mathicgb/QuadMatrix.hpp" #include "mathicgb/SparseMatrix.hpp" #include "mathicgb/F4MatrixReducer.hpp" #include "mathicgb/SparseMatrix.hpp" #include "mathicgb/CFile.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN namespace { static const char* QuadMatrixExtension = ".qmat"; static const char* LowerRightMatrixExtension = ".brmat"; static const char* ReducedLowerRightMatrixExtension = ".rbrmat"; /// Returns true if the file exists - or more precisely if it can be opened /// for reading. Using this function to create a file only if it does not /// exist implies a race condition in that the file could have been crated /// after checking if it exists and before (re)creating it. Do not use this /// approach if that is not acceptable. The advantage here is that this is /// portable. There could be a solution with freopen, but unfortunately /// freopen is allowed to fail on any change to the mode so it is not /// a portable solution. bool fileExists(const std::string fileName) { return CFile(fileName, "r", CFile::NoThrowTag()).hasFile(); } } MatrixAction::MatrixAction(): mParams(1, std::numeric_limits::max()) { mParams.registerFileNameExtension(QuadMatrixExtension); mParams.registerFileNameExtension(LowerRightMatrixExtension); mParams.registerFileNameExtension(ReducedLowerRightMatrixExtension); mParams.registerFileNameExtension("."); } void MatrixAction::directOptions( std::vector< std::string> tokens, mic::CliParser& parser ) { mParams.directOptions(tokens, parser); } void MatrixAction::performAction() { mParams.perform(); for (size_t i = 0; i < mParams.inputFileCount(); ++i) { const auto fileNameStem = mParams.inputFileNameStem(i); const auto extension = mParams.inputFileNameExtension(i); const auto quadFileName = fileNameStem + QuadMatrixExtension; const auto lowerRightFileName = fileNameStem + LowerRightMatrixExtension; const auto reducedLowerRightFileName = fileNameStem + ReducedLowerRightMatrixExtension; std::string inputFileName; SparseMatrix lowerRightMatrix; SparseMatrix::Scalar modulus; if ( extension == QuadMatrixExtension || extension == "." || extension == "" ) { inputFileName = quadFileName; CFile file(quadFileName, "rb"); QuadMatrix matrix; modulus = matrix.read(file.handle()); file.close(); lowerRightMatrix = F4MatrixReducer(modulus).reduceToBottomRight(matrix); if (!fileExists(lowerRightFileName)) { CFile file(lowerRightFileName, "wb"); lowerRightMatrix.write(modulus, file.handle()); CFile pbmFile(lowerRightFileName + ".pbm", "wb"); lowerRightMatrix.writePBM(pbmFile.handle()); } } else if (extension == LowerRightMatrixExtension) { inputFileName = lowerRightFileName; CFile file(lowerRightFileName, "rb"); modulus = lowerRightMatrix.read(file.handle()); } else { mathic::reportError ("Unknown input file extension of " + mParams.inputFileName(i)); } lowerRightMatrix = F4MatrixReducer(modulus). reducedRowEchelonForm(lowerRightMatrix); lowerRightMatrix.sortRowsByIncreasingPivots(); if (!fileExists(reducedLowerRightFileName)) { CFile file(reducedLowerRightFileName.c_str(), "wb"); lowerRightMatrix.write(modulus, file.handle()); CFile pbmFile(reducedLowerRightFileName + ".pbm", "wb"); lowerRightMatrix.writePBM(pbmFile.handle()); } else { SparseMatrix referenceMatrix; CFile file(reducedLowerRightFileName.c_str(), "rb"); referenceMatrix.read(file.handle()); if (lowerRightMatrix != referenceMatrix) { const std::string wrongFile = fileNameStem + ".out" + ReducedLowerRightMatrixExtension; const std::string wrongFilePbm = fileNameStem + ".out.pbm"; std::cerr << "Reducing " << inputFileName << " does not yield the matrix " << reducedLowerRightFileName << ".\n" << "Writing computed matrix to " << wrongFile << ".\n"; CFile file(wrongFile, "wb"); lowerRightMatrix.write(modulus, file.handle()); CFile filePbm(wrongFilePbm, "wb"); lowerRightMatrix.writePBM(filePbm.handle()); } else if (tracingLevel > 0) { std::cerr << "Match for " << inputFileName << " -> " << ReducedLowerRightMatrixExtension << ".\n"; } } } } const char* MatrixAction::staticName() { return "matrix"; } const char* MatrixAction::name() const { return staticName(); } const char* MatrixAction::description() const { return "Perform matrix computations. " "The name of the matrix file is an optional direct parameter."; } const char* MatrixAction::shortDescription() const { return "Perform matrix computations."; } void MatrixAction::pushBackParameters( std::vector& parameters ) { mParams.pushBackParameters(parameters); } MATHICGB_NAMESPACE_END mathicgb-master/src/cli/MatrixAction.hpp000077500000000000000000000015321311555162500206060ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MATRIX_ACTION_GUARD #define MATHICGB_MATRIX_ACTION_GUARD #include "CommonParams.hpp" #include MATHICGB_NAMESPACE_BEGIN /// Performs computations on matrices. class MatrixAction : public mathic::Action { public: MatrixAction(); virtual void directOptions( std::vector tokens, mic::CliParser& parser ); virtual void performAction(); static const char* staticName(); virtual const char* name() const; virtual const char* description() const; virtual const char* shortDescription() const; virtual void pushBackParameters(std::vector& parameters); private: CommonParams mParams; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/cli/SigGBAction.cpp000077500000000000000000000071501311555162500202720ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "SigGBAction.hpp" #include "mathicgb/Basis.hpp" #include "mathicgb/SignatureGB.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/Scanner.hpp" #include "mathicgb/MathicIO.hpp" #include #include MATHICGB_NAMESPACE_BEGIN SigGBAction::SigGBAction(): mUseSingularCriterionEarly( "earlySingularCriterion", "Apply the singular S-pair elimination criterion before queueing " "that S-pair. Otherwise, the criterion is only checked just before " "the S-pair would otherwise cause a polynomial reduction to occur. ", false), mPostponeKoszul( "postponeKoszul", "Postpone the construction of Koszul syzygy signatures.", true), mUseBaseDivisors( "useBaseDivisors", "Use high ratio and low ratio base divisors to eliminate " "S-spairs quickly based on signature.", true), mParams(1, 1) {} void SigGBAction::directOptions( std::vector< std::string> tokens, mic::CliParser& parser ) { mParams.directOptions(tokens, parser); } void SigGBAction::performAction() { mParams.perform(); mGBParams.perform(); // read input file const std::string inputBasisFile = mParams.inputFileNameStem(0) + ".ideal"; std::ifstream inputFile(inputBasisFile.c_str()); if (inputFile.fail()) mic::reportError("Could not read input file \"" + inputBasisFile + '\n'); Scanner in(inputFile); auto p = MathicIO<>().readRing(true, in); auto& ring = *p.first; auto& processor = p.second; auto basis = MathicIO<>().readBasis(ring, false, in); if (processor.schreyering()) processor.setSchreyerMultipliers(basis); SignatureGB alg( std::move(basis), std::move(processor), Reducer::reducerType(mGBParams.mReducer.value()), mGBParams.mMonoLookup.value(), mGBParams.mMonomialTable.value(), mPostponeKoszul.value(), mUseBaseDivisors.value(), mGBParams.mPreferSparseReducers.value(), mUseSingularCriterionEarly.value(), mGBParams.mSPairQueue.value()); alg.setBreakAfter(mGBParams.mBreakAfter.value()); alg.setPrintInterval(mGBParams.mPrintInterval.value()); alg.computeGrobnerBasis(); // print statistics alg.displayStats(std::cout); alg.displayPaperStats(std::cout); { std::ofstream statsOut(mParams.inputFileNameStem(0) + ".stats"); alg.displayStats(statsOut); alg.displayPaperStats(statsOut); } if (mGBParams.mOutputResult.value()) { // print basis { std::ofstream ogb(mParams.inputFileNameStem(0) + ".gb"); ogb << "-- gb: ----\n"; alg.getGB()->display(ogb); } // print syzygy basis { std::ofstream syzygyOut(mParams.inputFileNameStem(0) + ".syz"); syzygyOut << "-- syz: ----\n"; alg.getSyzTable()->display(syzygyOut); syzygyOut << std::endl; } } } const char* SigGBAction::staticName() { return "siggb"; } const char* SigGBAction::name() const { return staticName(); } const char* SigGBAction::description() const { return "Compute a signature Grobner basis. " "The project name is an optional direct parameter."; } const char* SigGBAction::shortDescription() const { return "Compute a signature Grobner basis"; } void SigGBAction::pushBackParameters( std::vector& parameters ) { mParams.pushBackParameters(parameters); mGBParams.pushBackParameters(parameters); parameters.push_back(&mUseSingularCriterionEarly); parameters.push_back(&mPostponeKoszul); parameters.push_back(&mUseBaseDivisors); } MATHICGB_NAMESPACE_END mathicgb-master/src/cli/SigGBAction.hpp000077500000000000000000000017501311555162500202770ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SIG_G_B_ACTION_GUARD #define MATHICGB_SIG_G_B_ACTION_GUARD #include "GBCommonParams.hpp" #include "CommonParams.hpp" #include MATHICGB_NAMESPACE_BEGIN class SigGBAction : public mic::Action { public: SigGBAction(); virtual void directOptions( std::vector tokens, mic::CliParser& parser ); virtual void performAction(); static const char* staticName(); virtual const char* name() const; virtual const char* description() const; virtual const char* shortDescription() const; virtual void pushBackParameters(std::vector& parameters); private: CommonParams mParams; GBCommonParams mGBParams; mic::BoolParameter mUseSingularCriterionEarly; mic::BoolParameter mPostponeKoszul; mic::BoolParameter mUseBaseDivisors; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb.cpp000077500000000000000000000662071311555162500172200ustar00rootroot00000000000000#include "mathicgb/stdinc.h" #include "mathicgb.h" #include "mathicgb/Basis.hpp" #include "mathicgb/PolyRing.hpp" #include "mathicgb/Poly.hpp" #include "mathicgb/Reducer.hpp" #include "mathicgb/ClassicGBAlg.hpp" #include "mathicgb/mtbb.hpp" #include "mathicgb/LogDomainSet.hpp" #include #ifndef MATHICGB_ASSERT #ifdef MATHICGB_DEBUG #include #define MATHICGB_ASSERT(X) assert(X) #else #define MATHICGB_ASSERT(X) #endif #endif #define MATHICGB_STREAM_CHECK(X, MSG) \ do { \ const bool value = (X); \ if (!value) { \ const bool ignoreMe = false; \ MATHICGB_ASSERT(( \ "MathicGB stream protocol error: "#MSG \ "\nAssert expression: "#X"\n", \ false \ )); \ throw std::invalid_argument( \ "MathicGB stream protocol error: "#MSG \ "\nAssert expression: "#X"\n" \ ); \ } \ } while (false) extern "C" { void libmathicgbIsPresent(void) {} char MATHICGB_VERSION_STRING[] = VERSION; } MATHICGB_NAMESPACE_BEGIN using namespace mgbi; namespace { bool isPrime(unsigned int n) { if (n == 0 || n == 1) return false; if (n == 2 || n == 3) return true; return true; // todo: make better test } }; bool logTime(const char* logName, double& time) { auto log = LogDomainSet::singleton().logDomain(logName); if (log == 0 || !log->enabled()) return false; time = log->loggedSecondsReal(); return true; } bool logNumber(const char* logName, double& number) { auto log = LogDomainSet::singleton().logDomain(logName); if (log == 0 || !log->enabled()) return false; number = static_cast(log->count()); return true; } namespace mgbi { struct StreamStateChecker::Pimpl { Pimpl(Coefficient modulus, VarIndex varCount, Component comCount): modulus(modulus), varCount(varCount), comCount(comCount), state(Initial), hasClaimedPolyCount(false), claimedPolyCount(0), seenPolyCount(0), hasClaimedTermCount(false), claimedTermCount(0), seenTermCount(0), lastVar(0) {} bool debugAssertValid() const; enum State { Initial, MakingIdeal, MakingPoly, MakingTerm, HasIdeal }; const Coefficient modulus; const VarIndex varCount; const Component comCount; State state; bool hasClaimedPolyCount; size_t claimedPolyCount; size_t seenPolyCount; bool hasClaimedTermCount; size_t claimedTermCount; size_t seenTermCount; VarIndex lastVar; }; bool StreamStateChecker::Pimpl::debugAssertValid() const { #ifdef MATHICGB_DEBUG MATHICGB_ASSERT(this != 0); switch (state) { case Initial: case MakingIdeal: case MakingPoly: case MakingTerm: case HasIdeal: break; default: MATHICGB_ASSERT(false); return false; } #endif return true; }; StreamStateChecker::StreamStateChecker( const Coefficient modulus, const VarIndex varCount, const Component comCount ): mPimpl(new Pimpl(modulus, varCount, comCount)) { try { MATHICGB_STREAM_CHECK(isPrime(modulus), "The modulus must be prime"); MATHICGB_ASSERT(mPimpl->debugAssertValid()); } catch (...) { delete mPimpl; } } StreamStateChecker::~StreamStateChecker() { MATHICGB_ASSERT(mPimpl->debugAssertValid()); delete mPimpl; } void StreamStateChecker::idealBegin() { MATHICGB_ASSERT(mPimpl->debugAssertValid()); MATHICGB_STREAM_CHECK( mPimpl->state == Pimpl::Initial || mPimpl->state == Pimpl::HasIdeal, "idealBegin() must not be called twice " "without an intervening call to idealDone()." ); mPimpl->state = Pimpl::MakingIdeal; mPimpl->hasClaimedPolyCount = false; mPimpl->claimedPolyCount = 0; mPimpl->seenPolyCount = 0; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::idealBegin(size_t polyCount) { idealBegin(); mPimpl->hasClaimedPolyCount = true; mPimpl->claimedPolyCount = polyCount; mPimpl->seenPolyCount = 0; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::appendPolynomialBegin() { MATHICGB_ASSERT(mPimpl->debugAssertValid()); MATHICGB_STREAM_CHECK( mPimpl->state != Pimpl::Initial && mPimpl->state != Pimpl::HasIdeal, "appendPolynomialBegin() must only be called after idealBegin() and " "before idealEnd()." ); MATHICGB_STREAM_CHECK( mPimpl->state == Pimpl::MakingIdeal, "appendPolynomialBegin() must not be called twice without " "an intervening call to appendPolynomialDone()." ); MATHICGB_STREAM_CHECK( !mPimpl->hasClaimedPolyCount || mPimpl->seenPolyCount < mPimpl->claimedPolyCount, "The number of polynomials in an ideal must not exceed the amount " "passed to idealBegin()." ); mPimpl->state = Pimpl::MakingPoly; mPimpl->seenPolyCount += 1; mPimpl->hasClaimedTermCount = false; mPimpl->claimedTermCount = 0; mPimpl->seenTermCount = 0; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::appendPolynomialBegin(size_t termCount) { appendPolynomialBegin(); mPimpl->hasClaimedTermCount = true; mPimpl->claimedTermCount = termCount; mPimpl->seenTermCount = 0; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::appendTermBegin(const Component com) { MATHICGB_ASSERT(mPimpl->debugAssertValid()); MATHICGB_STREAM_CHECK( mPimpl->state != Pimpl::Initial && mPimpl->state != Pimpl::HasIdeal && mPimpl->state != Pimpl::MakingIdeal, "appendTermBegin() must only be called after appendPolynomialBegin() " "and before appendPolynomialDone()." ); MATHICGB_STREAM_CHECK( mPimpl->state == Pimpl::MakingPoly, "appendTermBegin() must not be called twice without an intervening " "call to appendTermDone()." ); MATHICGB_STREAM_CHECK( !mPimpl->hasClaimedTermCount || mPimpl->seenTermCount < mPimpl->claimedTermCount, "The number of terms in a polynomial must not exceed the amount " "passed to appendPolynomialBegin()." ); MATHICGB_STREAM_CHECK( com < mPimpl->comCount, "The component passed to appendTermBegin must be strictly less " "than the number of components." ); mPimpl->state = Pimpl::MakingTerm; mPimpl->seenTermCount += 1; mPimpl->lastVar = std::numeric_limitslastVar)>::max(); MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::appendExponent(VarIndex index, Exponent exponent) { MATHICGB_ASSERT(mPimpl->debugAssertValid()); MATHICGB_STREAM_CHECK( mPimpl->state == Pimpl::MakingTerm, "appendExponent must only be called after appendTermBegin() and before " "appendTermDone()." ); MATHICGB_STREAM_CHECK( index < mPimpl->varCount, "The index passed to appendExponent must be strictly less than " "the number of variables." ); MATHICGB_STREAM_CHECK( mPimpl->lastVar == std::numeric_limitslastVar)>::max() || mPimpl->lastVar < index, "The variable indices passed to appendExponent must be in strictly " "increasing order within each monomial." ); mPimpl->lastVar = index; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::appendTermDone(Coefficient coefficient) { MATHICGB_ASSERT(mPimpl->debugAssertValid()); MATHICGB_STREAM_CHECK( coefficient > 0, "The coefficient passed to appendTermDone() must be strictly positive." ); MATHICGB_STREAM_CHECK( coefficient < mPimpl->modulus, "The coefficient passed to appendTermDone() must be strictly less " "then the modulus." ); MATHICGB_STREAM_CHECK( mPimpl->state == Pimpl::MakingTerm, "appendTermDone() must only be called after appendTermBegin()." ); mPimpl->state = Pimpl::MakingPoly; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::appendPolynomialDone() { MATHICGB_ASSERT(mPimpl->debugAssertValid()); MATHICGB_STREAM_CHECK( mPimpl->state == Pimpl::MakingPoly, "appendPolynomialDone() must only be called after appendPolynomialBegin()." ); MATHICGB_STREAM_CHECK( !mPimpl->hasClaimedTermCount || mPimpl->seenTermCount == mPimpl->claimedTermCount, "The number of terms in a polynomial must match the amount " "passed to appendPolynomialBegin()." ); mPimpl->state = Pimpl::MakingIdeal; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } void StreamStateChecker::idealDone() { MATHICGB_ASSERT(mPimpl->debugAssertValid()); MATHICGB_STREAM_CHECK( mPimpl->state == Pimpl::MakingIdeal, "idealDone() must only be called after idealBegin()." ); MATHICGB_STREAM_CHECK( !mPimpl->hasClaimedPolyCount || mPimpl->seenPolyCount == mPimpl->claimedPolyCount, "The number of polynomials in an ideal must match the amount " "passed to idealBegin()." ); mPimpl->state = Pimpl::HasIdeal; MATHICGB_ASSERT(mPimpl->debugAssertValid()); } bool StreamStateChecker::hasIdeal() const { MATHICGB_ASSERT(mPimpl->debugAssertValid()); return mPimpl->state == Pimpl::HasIdeal; } } // ** Implementation of the class GroebnerConfiguration struct GroebnerConfiguration::Pimpl { Pimpl( Coefficient modulus, VarIndex varCount, Component comCount ): mModulus(modulus), mVarCount(varCount), mComCount(comCount), mBaseOrder(RevLexDescendingBaseOrder), mGradings(varCount, 1), mComponentBefore(ComponentAfterBaseOrder), mComponentsAscending(true), mSchreyering(true), mReducer(DefaultReducer), mMaxSPairGroupSize(0), mMaxThreadCount(0), mLogging(), mCallbackData(0), mCallback(0) #ifdef MATHICGB_DEBUG , mHasBeenDestroyed(false) #endif { } ~Pimpl() { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mHasBeenDestroyed = true;) } static bool baseOrderValid(const BaseOrder order) { return order == RevLexDescendingBaseOrder || order == LexDescendingBaseOrder || order == RevLexAscendingBaseOrder || order == LexAscendingBaseOrder; } static bool reducerValid(const Reducer reducer) { return reducer == DefaultReducer || reducer == ClassicReducer || reducer == MatrixReducer; } bool debugAssertValid() const { #ifdef MATHICGB_DEBUG MATHICGB_ASSERT(this != 0); MATHICGB_ASSERT(baseOrderValid(mBaseOrder)); MATHICGB_ASSERT(reducerValid(mReducer)); MATHICGB_ASSERT(mModulus != 0); MATHICGB_ASSERT(mCallback != 0 || mCallbackData == 0); MATHICGB_ASSERT_NO_ASSUME(!mHasBeenDestroyed); #endif return true; } const Coefficient mModulus; const VarIndex mVarCount; const Component mComCount; BaseOrder mBaseOrder; std::vector mGradings; size_t mComponentBefore; bool mComponentsAscending; bool mSchreyering; Reducer mReducer; unsigned int mMaxSPairGroupSize; unsigned int mMaxThreadCount; std::string mLogging; void* mCallbackData; Callback::Action (*mCallback) (void*); MATHICGB_IF_DEBUG(bool mHasBeenDestroyed); }; GroebnerConfiguration::GroebnerConfiguration( Coefficient modulus, VarIndex varCount, Component comCount ): mPimpl(new Pimpl(modulus, varCount, comCount)) { if (modulus > std::numeric_limits::max()) { MATHICGB_ASSERT_NO_ASSUME(false); std::ostringstream str; str << "Modulus " << modulus << " is too large. MathicGB only supports 16 bit moduli."; mathic::reportError(str.str()); } if (!isPrime(modulus)) { MATHICGB_ASSERT_NO_ASSUME(false); std::ostringstream str; str << "Modulus " << modulus << " is not prime. MathicGB only supports prime fields."; mathic::reportError(str.str()); } MATHICGB_ASSERT(mPimpl->debugAssertValid()); } GroebnerConfiguration::GroebnerConfiguration( const GroebnerConfiguration& conf ): mPimpl(new Pimpl(*conf.mPimpl)) { MATHICGB_ASSERT(conf.mPimpl->debugAssertValid()); } GroebnerConfiguration::~GroebnerConfiguration() { MATHICGB_ASSERT(mPimpl->debugAssertValid()); delete mPimpl; } auto GroebnerConfiguration::modulus() const -> Coefficient { return mPimpl->mModulus; } auto GroebnerConfiguration::varCount() const -> VarIndex { return mPimpl->mVarCount; } auto GroebnerConfiguration::comCount() const -> Component { return mPimpl->mComCount; } const char* GroebnerConfiguration::baseOrderName(BaseOrder order) { switch (order) { case RevLexDescendingBaseOrder: return "reverse lexicographic descending"; case LexDescendingBaseOrder: return "lexicographic descending"; case RevLexAscendingBaseOrder: return "reverse lexicographic ascending"; case LexAscendingBaseOrder: return "lexicographic ascending"; default: return "(ERROR: invalid base order)"; } } bool GroebnerConfiguration::setMonomialOrderInternal( MonomialOrderData order ) { MATHICGB_ASSERT(Pimpl::baseOrderValid(order.baseOrder)); MATHICGB_ASSERT(varCount() != 0 || order.gradingsSize == 0); MATHICGB_ASSERT(varCount() == 0 || order.gradingsSize % varCount() == 0); // Check if order is global. if (varCount() != 0) { const size_t rowCount = order.gradingsSize / varCount(); for (VarIndex var = 0; var < varCount(); ++var) { // check if 1 < x_var. for (size_t row = 0; row < rowCount; ++row) { const Exponent e = order.gradings[row * varCount() + var]; if (e < 0) return false; // order not global if (e > 0) goto orderGlobalForVar; } if ( order.baseOrder == RevLexAscendingBaseOrder || order.baseOrder == RevLexDescendingBaseOrder ) return false; // order not global orderGlobalForVar:; } } mPimpl->mBaseOrder = order.baseOrder; mPimpl->mGradings.assign (order.gradings, order.gradings + order.gradingsSize); return true; } auto GroebnerConfiguration::monomialOrderInternal() const -> MonomialOrderData { const MonomialOrderData data = { mPimpl->mBaseOrder, mPimpl->mGradings.data(), mPimpl->mGradings.size() }; return data; } void GroebnerConfiguration::setCallbackInternal( void* data, Callback::Action (*func) (void*) ) { MATHICGB_ASSERT(func != 0 || data == 0); mPimpl->mCallbackData = data; mPimpl->mCallback = func; } void* GroebnerConfiguration::callbackDataInternal() const { return mPimpl->mCallbackData; } void GroebnerConfiguration::setComponentBefore(size_t value) { mPimpl->mComponentBefore = value; } size_t GroebnerConfiguration::componentBefore() const { return mPimpl->mComponentBefore; } void GroebnerConfiguration::setComponentsAscending(bool value) { mPimpl->mComponentsAscending = value; } bool GroebnerConfiguration::componentsAscending() const { return mPimpl->mComponentsAscending; } void GroebnerConfiguration::setSchreyering(bool value) { mPimpl->mSchreyering = value; } bool GroebnerConfiguration::schreyering() const { return mPimpl->mSchreyering; } void GroebnerConfiguration::setReducer(Reducer reducer) { MATHICGB_ASSERT(Pimpl::reducerValid(reducer)); mPimpl->mReducer = reducer; } auto GroebnerConfiguration::reducer() const -> Reducer { return mPimpl->mReducer; } void GroebnerConfiguration::setMaxSPairGroupSize(unsigned int size) { mPimpl->mMaxSPairGroupSize = size; } uint32 GroebnerConfiguration::maxSPairGroupSize() const { return mPimpl->mMaxSPairGroupSize; } void GroebnerConfiguration::setMaxThreadCount(unsigned int maxThreadCount) { mPimpl->mMaxThreadCount = maxThreadCount; } unsigned int GroebnerConfiguration::maxThreadCount() const { return mPimpl->mMaxThreadCount; } void GroebnerConfiguration::setLogging(const char* logging) { if (logging == 0) mPimpl->mLogging.clear(); else mPimpl->mLogging = logging; } const char* GroebnerConfiguration::logging() const { return mPimpl->mLogging.c_str(); } // ** Implementation of class GroebnerInputIdealStream namespace { PolyRing::Monoid::Order::BaseOrder translateBaseOrder( const GroebnerConfiguration::BaseOrder baseOrder ) { typedef PolyRing::Monoid::Order Internal; typedef GroebnerConfiguration External; switch (baseOrder) { default: MATHICGB_ASSERT(false); case External:: RevLexDescendingBaseOrder: return Internal::RevLexBaseOrderFromRight; case External::LexDescendingBaseOrder: return Internal::LexBaseOrderFromLeft; case External::RevLexAscendingBaseOrder: return Internal::RevLexBaseOrderFromLeft; case External::LexAscendingBaseOrder: return Internal::LexBaseOrderFromRight; } } } struct GroebnerInputIdealStream::Pimpl { Pimpl(const GroebnerConfiguration& conf): ring( PolyRing::Field(conf.modulus()), PolyRing::Monoid::Order( conf.varCount(), std::move(conf.monomialOrder().second), translateBaseOrder(conf.monomialOrder().first), conf.componentBefore(), conf.componentsAscending(), conf.schreyering() ) ), basis(ring), poly(ring), monomial(ring.allocMonomial()), conf(conf) #ifdef MATHICGB_DEBUG , hasBeenDestroyed(false), checker(conf.modulus(), conf.varCount(), conf.comCount()) #endif {} ~Pimpl() { ring.freeMonomial(monomial); } const PolyRing ring; Basis basis; Poly poly; Monomial monomial; const GroebnerConfiguration conf; MATHICGB_IF_DEBUG(bool hasBeenDestroyed); MATHICGB_IF_DEBUG(StreamStateChecker checker); }; GroebnerInputIdealStream::GroebnerInputIdealStream( const GroebnerConfiguration& conf ): mExponents(new Exponent[conf.varCount()]), mPimpl(new Pimpl(conf)) { MATHICGB_ASSERT(debugAssertValid()); } GroebnerInputIdealStream::~GroebnerInputIdealStream() { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(mExponents != 0); MATHICGB_ASSERT(mPimpl != 0); MATHICGB_ASSERT_NO_ASSUME(!mPimpl->hasBeenDestroyed); MATHICGB_IF_DEBUG(mPimpl->hasBeenDestroyed = true); delete mPimpl; delete[] mExponents; } const GroebnerConfiguration& GroebnerInputIdealStream::configuration() const { return mPimpl->conf; } auto GroebnerInputIdealStream::modulus() const -> Coefficient { return configuration().modulus(); } auto GroebnerInputIdealStream::varCount() const -> VarIndex { return configuration().varCount(); } auto GroebnerInputIdealStream::comCount() const -> Component { return configuration().comCount(); } void GroebnerInputIdealStream::idealBegin() { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.idealBegin()); MATHICGB_ASSERT(mPimpl->poly.isZero()); MATHICGB_ASSERT(mPimpl->basis.empty()); MATHICGB_ASSERT(debugAssertValid()); } void GroebnerInputIdealStream::idealBegin(size_t polyCount) { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.idealBegin(polyCount)); MATHICGB_ASSERT(mPimpl->poly.isZero()); MATHICGB_ASSERT(mPimpl->basis.empty()); mPimpl->basis.reserve(polyCount); MATHICGB_ASSERT(debugAssertValid()); } void GroebnerInputIdealStream::appendPolynomialBegin() { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.appendPolynomialBegin()); MATHICGB_ASSERT(mPimpl->poly.isZero()); MATHICGB_ASSERT(debugAssertValid()); } void GroebnerInputIdealStream::appendPolynomialBegin(size_t termCount) { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.appendPolynomialBegin(termCount)); MATHICGB_ASSERT(mPimpl->poly.isZero()); mPimpl->poly.reserve(termCount); MATHICGB_ASSERT(debugAssertValid()); } void GroebnerInputIdealStream::appendTermBegin(const Component com) { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.appendTermBegin(com)); std::fill_n(mExponents, varCount(), 0); mPimpl->ring.monoid().setComponent(com, mPimpl->monomial); MATHICGB_ASSERT(debugAssertValid()); } void GroebnerInputIdealStream::appendTermDone(Coefficient coefficient) { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.appendTermDone(coefficient)); // @todo: do this directly into the polynomial instead of copying a second // time. mPimpl->ring.monomialSetExternalExponents(mPimpl->monomial, mExponents); mPimpl->poly.append(coefficient, mPimpl->monomial); MATHICGB_ASSERT(debugAssertValid()); } void GroebnerInputIdealStream::appendPolynomialDone() { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.appendPolynomialDone()); // todo: avoid copy here by the following changes // todo: give Ideal a Poly&& insert // todo: give Poly a Poly&& constructor auto poly = make_unique(std::move(mPimpl->poly)); if (!poly->termsAreInDescendingOrder()) *poly = poly->polyWithTermsDescending(); mPimpl->basis.insert(std::move(poly)); mPimpl->poly.setToZero(); MATHICGB_ASSERT(debugAssertValid()); } void GroebnerInputIdealStream::idealDone() { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_IF_DEBUG(mPimpl->checker.idealDone()); } bool GroebnerInputIdealStream::debugAssertValid() const { MATHICGB_ASSERT(this != 0); MATHICGB_ASSERT(mExponents != 0); MATHICGB_ASSERT(mPimpl != 0); MATHICGB_ASSERT_NO_ASSUME(!mPimpl->hasBeenDestroyed); MATHICGB_ASSERT(!mPimpl->monomial.isNull()); MATHICGB_ASSERT(&mPimpl->basis.ring() == &mPimpl->ring); MATHICGB_ASSERT(&mPimpl->poly.ring() == &mPimpl->ring); MATHICGB_ASSERT(mPimpl->ring.getNumVars() == mPimpl->conf.varCount()); MATHICGB_ASSERT(mPimpl->ring.charac() == mPimpl->conf.modulus()); return true; } // ** Implementation of class mgbi::PimplOf namespace mgbi { class PimplOf { public: template typename T::Pimpl& operator()(T& t) { MATHICGB_ASSERT(t.mPimpl != 0); return *t.mPimpl; } }; } // ** Implementation of mgbi::IdealAdapter namespace mgbi { struct IdealAdapter::Pimpl { Pimpl(): polyIndex(0), mTermIt() {} std::unique_ptr basis; std::unique_ptr tmpTerm; size_t polyIndex; Poly::ConstTermIterator mTermIt; }; IdealAdapter::IdealAdapter(): mPimpl(new Pimpl()) {} IdealAdapter::~IdealAdapter() { MATHICGB_ASSERT(mPimpl != 0); delete mPimpl; } auto IdealAdapter::varCount() const -> VarIndex { MATHICGB_ASSERT(mPimpl->basis.get() != 0); return mPimpl->basis->ring().getNumVars(); } size_t IdealAdapter::polyCount() const { MATHICGB_ASSERT(mPimpl->basis.get() != 0); return mPimpl->basis->size(); } size_t IdealAdapter::termCount(PolyIndex poly) const { MATHICGB_ASSERT(mPimpl->basis.get() != 0); MATHICGB_ASSERT(poly < mPimpl->basis->size()); return mPimpl->basis->getPoly(poly)->termCount(); } void IdealAdapter::toFirstTerm() { mPimpl->polyIndex = 0; while ( mPimpl->polyIndex < mPimpl->basis->size() && mPimpl->basis->getPoly(mPimpl->polyIndex)->isZero() ) ++(mPimpl->polyIndex); if (mPimpl->polyIndex < mPimpl->basis->size()) mPimpl->mTermIt = mPimpl->basis->getPoly(mPimpl->polyIndex)->begin(); } auto IdealAdapter::nextTerm() const -> ConstTerm { MATHICGB_ASSERT(mPimpl->basis.get() != 0); MATHICGB_ASSERT(mPimpl->polyIndex < mPimpl->basis->size()); const auto& monoid = mPimpl->basis->ring().monoid(); const auto& p = *mPimpl->basis->getPoly(mPimpl->polyIndex); MATHICGB_ASSERT(p.ring().monoid() == monoid); const auto& from = *mPimpl->mTermIt; const auto com = monoid.component(*from.mono); auto to = mPimpl->tmpTerm.get(); for (VarIndex var = 0; var < monoid.varCount(); ++var) to[var] = monoid.externalExponent(*from.mono, var); ++(mPimpl->mTermIt); if (mPimpl->mTermIt == p.end()) { ++mPimpl->polyIndex; while ( mPimpl->polyIndex < mPimpl->basis->size() && mPimpl->basis->getPoly(mPimpl->polyIndex)->isZero() ) ++(mPimpl->polyIndex); if (mPimpl->polyIndex < mPimpl->basis->size()) mPimpl->mTermIt = mPimpl->basis->getPoly(mPimpl->polyIndex)->begin(); } ConstTerm term; term.coef = from.coef; term.exponents = to; term.com = com; return term; } } namespace { class CallbackAdapter { public: typedef mgb::GroebnerConfiguration::Callback::Action Action; CallbackAdapter(void* data, Action (*callback) (void*)): mData(data), mCallback(callback), mLastAction(Action::ContinueAction) { MATHICGB_ASSERT(mCallback != 0 || mData == 0); } const bool isNull() const {return mCallback == 0;} Action lastAction() const {return mLastAction;} bool operator()() { if (isNull()) return true; mLastAction = mCallback(mData); return mLastAction == Action::ContinueAction; } private: void* const mData; Action (* const mCallback) (void*); Action mLastAction; }; } // ** Implementation of function mgbi::internalComputeGroebnerBasis namespace mgbi { bool internalComputeGroebnerBasis( GroebnerInputIdealStream& inputWhichWillBeCleared, IdealAdapter& output ) { /// @todo: make a scheme where the output Groebner basis is freed /// polynomial-by-polynomial as data is transferred to out. Also /// make it so that ideal is not copied. auto&& basis = PimplOf()(inputWhichWillBeCleared).basis; auto&& conf = inputWhichWillBeCleared.configuration(); auto&& ring = basis.ring(); const auto varCount = ring.getNumVars(); MATHICGB_ASSERT(PimplOf()(conf).debugAssertValid()); // Tell tbb how many threads to use const auto maxThreadCount = int(conf.maxThreadCount()); const auto tbbMaxThreadCount = maxThreadCount == 0 ? mgb::mtbb::task_scheduler_init::automatic : maxThreadCount; mgb::mtbb::task_scheduler_init scheduler(tbbMaxThreadCount); // Set up logging LogDomainSet::singleton().reset(); LogDomainSet::singleton().performLogCommands(conf.logging()); // Make reducer typedef GroebnerConfiguration GConf; Reducer::ReducerType reducerType; switch (conf.reducer()) { case GConf::ClassicReducer: reducerType = Reducer::Reducer_Geobucket_Hashed; break; default: case GConf::DefaultReducer: case GConf::MatrixReducer: reducerType = Reducer::Reducer_F4_New; break; } const auto reducer = Reducer::makeReducer(reducerType, ring); CallbackAdapter callback( PimplOf()(conf).mCallbackData, PimplOf()(conf).mCallback ); ClassicGBAlgParams params; params.reducer = reducer.get(); params.monoLookupType = 2; params.preferSparseReducers = true; params.sPairQueueType = 0; params.breakAfter = 0; params.printInterval = 0; params.sPairGroupSize = conf.maxSPairGroupSize(); params.reducerMemoryQuantum = 100 * 1024; params.useAutoTopReduction = true; params.useAutoTailReduction = false; params.callback = nullptr; if (!callback.isNull()) params.callback = [&callback](){return callback();}; auto gb = conf.comCount() == 1 ? computeGBClassicAlg(std::move(basis), params) : computeModuleGBClassicAlg(std::move(basis), params); typedef mgb::GroebnerConfiguration::Callback::Action Action; if (callback.lastAction() != Action::StopWithNoOutputAction) { PimplOf()(output).basis = make_unique(std::move(gb)); PimplOf()(output).tmpTerm = make_unique_array(basis.ring().varCount()); return true; } else return false; } } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb.h000077500000000000000000001020471311555162500166560ustar00rootroot00000000000000#ifndef MATHICGB_MATHICGB_GUARD #define MATHICGB_MATHICGB_GUARD #include #include #include // The main function in this file is computeGroebnerBasis. See the comment // preceding that function for an example of how to use this library // interface. extern "C" { // Put a C function in the library so that it can be detected by the autoconf // macro AC_CHECK_LIB. That macro can only check for libraries that contain // at least one C function. void libmathicgbIsPresent(void); // This function does nothing. extern char MATHICGB_VERSION_STRING[]; } #define MATHICGB_VERSION VERSION /// The classes and functions in this namespace make up the public interface /// of MathicGB. You should not have to update your code when upgrading to a /// newer minor revision of MathicGB if you only use the public interface. namespace mgb { // Part of the public interface of MathicGB /// Code in this namespace is not part of the public interface of MathicGB. /// If you take a dependency on code in this namespace, except indirectly /// through using code in the mgb namespace, then you are not using the /// library interface as intended. namespace mgbi { // Not part of the public interface of MathicGB class PimplOf; } /// Sets time to the number of seconds accumulated on the internal /// MathicGB log named logName. Returns true if the logName log was /// found and false otherwise. /// /// The available logs and what they measure are not part of /// the public interface of MathicGB and indeed the availability of a log /// depends on both compile-time and run-time events. Therefore you must /// ensure that your program works even if this function always returns /// false. bool logTime(const char* logName, double& time); /// As logTime, but retrieves a number associated to logName that is /// not necessarily a time. bool logNumber(const char* logName, double& number); /// Use this class to describe a configuration of a Groebner basis algorithm /// that you want to run. /// /// If you came here to compute the Groebner basis of an ideal in a /// polynomial ring and you don't want to deal with modules: Don't worry /// about it. A module with one component over a polynomial ring is the /// same thing as that ring. Simply set the componentCount to 1. Then all /// (module) monomials will have component 0 and you can just ignore that. /// The internal implementation has a special case for this case you will /// not pay an overhead for this other than passing a few 0 components /// through the interface. /// /// @todo: expose more of the available functionality. class GroebnerConfiguration { public: // Type for the coefficient of a term. 2*x is a term with coefficient 2. typedef unsigned int Coefficient; /// Type to specify a variable in the polynomial ring. If the variables /// are x, y, z in that order, then x has index 0, y has index 1 and z /// has index 2. typedef size_t VarIndex; /// Type for the exponent of a variable. If x is a variable, then /// x*x = x^2 has exponent 2. typedef int Exponent; /// Type for the component of a module monomial. The module monomial /// x*y*z * e_i has component i. typedef unsigned int Component; /// A configuration in a module over a polynomial ring with varCount /// variables and the coefficients are from the finite field with /// modulus elements. modulus must be a prime. The module has the basis /// e_0, ..., e_k where k is componentCount - 1. GroebnerConfiguration( Coefficient modulus, VarIndex varCount, Component comCount ); GroebnerConfiguration(const GroebnerConfiguration& conf); ~GroebnerConfiguration(); Coefficient modulus() const; VarIndex varCount() const; Component comCount() const; enum BaseOrder { /// Reverse lexicographic order with x_1 > x_2 > ... > x_n. /// Can be described as rev-lex-descending or rev-lex-from-right. /// This is what people usually mean when they say rev-lex. RevLexDescendingBaseOrder = 0, /// Lexicographic order with x_1 > x_2 > ... > x_n. /// Can be described as lex-descending or lex-from-left. /// This is what people usually mean when they say lex. LexDescendingBaseOrder = 1, /// Reverse lexicographic order with x_1 < x_2 < ... < x_n. /// Can be described as rev-lex-ascending or rev-lex-from-left. RevLexAscendingBaseOrder = 2, /// Lexicographic order with x_1 < x_2 < ... < x_n. /// Can be described as lex-ascending or lex-from-right. LexAscendingBaseOrder = 3 }; /// Returns a name for the passed in base order. /// Ownership of the string is not passed on. You should not depend on /// the string having any particular value, except that it is something /// that will identify the order to a human. static const char* baseOrderName(BaseOrder order); /// Specifies the monomial order to compute a Groebner basis with /// respect to. You must ensure that the order that you are specifying /// is in fact a monomial order. /// /// The specified monomial order has two parts - a set of gradings and /// a base order. The base order is used to break ties for monomials with /// identical grades. /// /// The gradings parameter represents a matrix where each row of the matrix /// defines a grading. The matrix is represented in row-major order. /// The matrix has varCount() columns so gradings.size() must be a multiple /// of varCount(). /// /// Suppose gradings has one row U and that x^a and x^b are two monomials /// with exponent vectors a and b respectively. Then a < b if a*U < b*U /// where * is dot product. If there are several rows in gradings, then /// the first row U is considered first. If a*U=b*U then the second row /// is considered and so on. If a and b have the same degree with respect /// to all the rows of the matrix, then the base order is used to break the /// tie. /// /// An order is global if 1 is the smallest of all monomials. Equivalently, /// if 1 < x for each variable x in the ambient ring. In MathicGB only /// global orders are considered monomial orders and non-global orders /// are not supported. setMonomialOrder will return true if the specified /// order is global. Otherwise, setMonomialOrder returns false and the /// requested order is NOT set. So you can ignore the return value if /// and only if you are certain that the order you are requesting is in /// fact global. For example, ungraded reverse lex is not a (global) monomial /// order. /// /// Each row of the matrix adds overhead to the Groebner basis /// computation both in terms of time and space. /// /// The default grading is (1, ..., 1)-graded reverse lex. bool setMonomialOrder( BaseOrder order, const std::vector& gradings ); std::pair > monomialOrder() const; static const size_t ComponentAfterBaseOrder = static_cast(-1); /// Sets the module monomial order. This order extends the /// monomial order in the sense that a aM R and componentBefore != /// ComponentAfterBaseOrder, then that is an invalid value and you /// will experience undefined behavior. This is only checked at a /// later stage, so there is no problem in setting a value that /// was invalid at the time but that becomes valid later, either /// because you reset it to something valid or because you change the /// matrix. /// /// Setting this value to anything other than /// ComponentAfterBaseOrder incurs overhead similar to adding a /// row to the comparison matrix. /// /// The default value is ComponentAfterBaseOrder. void setComponentBefore(size_t value); VarIndex componentBefore() const; /// This setting modifies the module monomial order. /// If componentsAscending is true then a comparison of components /// is done such that a module monomial with greater component is /// considered greater once we get the point where components are /// compared. So when not using the Schreyer setting, the impact is: /// /// true value: e_0 < e_1 < ... < e_n /// false value: e_n < ... < e_1 < e_0. /// /// The default value is true. Either setting is implemented with a /// pre-processing step, so there is little-to-no overhead for it. void setComponentsAscending(bool value); bool componentsAscending() const; /// This setting modifies the module monomial order. /// We are Schreyering if we are using an ordering <' that is /// derived from the usual module mononial order < in the /// following way. Let c_i be the leading monomial of the input /// basis element with index i. Then /// /// ae_i <' be_i if and only if ac_ie_i < bc_je_j. /// /// The default value is true. Either setting is implemented with a /// pre-processing step, so there is little-to-no overhead. /// /// A possible future extension would be to allow setting the c_i /// to be something other than leading monomials. This would be useful /// for the higher levels in computation of resolutions. This /// functionality is not currently available. void setSchreyering(bool value); bool schreyering() const; enum Reducer { DefaultReducer = 0, /// Let the library decide for itself. ClassicReducer = 1, /// The classic polynomial division algorithm. MatrixReducer = 2 /// use linear algebra as in F4. }; /// Specify the way that polynoials are reduced. void setReducer(Reducer reducer); Reducer reducer() const; /// Sets the maximum number of S-pairs to reduce at one time. This is /// mainly useful as a (weak) control on memory usage for F4 reducers. /// A value of 0 indicates to let the library decide this value for /// itself, which is also the default and highly recommended value. /// /// For matrix-based reducers, use a high value. For serial classic /// reduction, use a low value, preferably 1. Setting the value to /// 0 already takes care of this. void setMaxSPairGroupSize(unsigned int size); unsigned int maxSPairGroupSize() const; /// Sets the maximum number of threads to use. May use fewer threads. /// A value of 0 indicates to let the library decide this value for /// itself, which is also the default value. void setMaxThreadCount(unsigned int maxThreadCount); unsigned int maxThreadCount() const; /// Sets logging to occur according to the string. The format of the /// string is the same as for the -logs command line parameter. /// Ownership of the string is not taken over. /// @todo: describe the format in more detail. void setLogging(const char* logging); const char* logging() const; /// Class used for setCallback(). class Callback { public: enum Action { ContinueAction = 0, StopWithNoOutputAction = 1, StopWithPartialOutputAction = 2 }; virtual Action call() = 0; }; /// Set callback to be called at various unspecified times during /// the computation. Callback has the ability to stop or continue /// the computation based on its return value. If callback is null /// then no function will be called. void setCallback(Callback* callback); Callback* callback(); const Callback* callback() const; private: friend class mgbi::PimplOf; void operator=(const GroebnerConfiguration&); // not available bool operator==(const GroebnerConfiguration&); // not available struct MonomialOrderData { BaseOrder baseOrder; const Exponent* gradings; size_t gradingsSize; }; bool setMonomialOrderInternal(MonomialOrderData order); MonomialOrderData monomialOrderInternal() const; static Callback::Action callbackCaller(void* obj); void setCallbackInternal(void* data, Callback::Action (*func) (void*)); void* callbackDataInternal() const; struct Pimpl; Pimpl* const mPimpl; }; /// After making a configuration, use this class to communicate a basis /// of the input ideal that you want to run a Groebner basis algorithm on. class GroebnerInputIdealStream { public: GroebnerInputIdealStream(const GroebnerConfiguration& conf); ~GroebnerInputIdealStream(); typedef GroebnerConfiguration::Coefficient Coefficient; typedef GroebnerConfiguration::VarIndex VarIndex; typedef GroebnerConfiguration::Exponent Exponent; typedef GroebnerConfiguration::Component Component; const GroebnerConfiguration& configuration() const; Coefficient modulus() const; VarIndex varCount() const; Component comCount() const; void idealBegin(); void idealBegin(size_t polyCount); void appendPolynomialBegin(); void appendPolynomialBegin(size_t termCount); /// Signals the beginning of communication of a module term of the /// current module element. void appendTermBegin(Component com); /// The sequence of indices appended to a term must be in strictly /// ascending order. void appendExponent(VarIndex index, Exponent exponent); void appendTermDone(Coefficient coefficient); void appendPolynomialDone(); void idealDone(); private: bool debugAssertValid() const; Exponent* const mExponents; struct Pimpl; friend class mgbi::PimplOf; Pimpl* const mPimpl; }; /// After making a configuration and an ideal, use this function to compute /// a Groebner basis. The output basis is constructed on output, which must /// resemble GroebnerInputIdealStream by having the following functions. /// /// - modulus() const; /// - varCount() const; /// - idealBegin(size_t polyCount); /// - void appendPolynomialBegin(size_t termCount); /// - void appendTermBegin(Component com); /// - void appendExponent(VarIndex index, Exponent exponent); /// - void appendTermDone(Coefficient coefficient); /// - void appendPolynomialDone(); /// - void idealDone(); /// /// ** Example /// /// This example uses a default configuration, constructs an ideal and then /// outputs the Groebner basis to a NullIdealStream which does not do /// anything with the output. However, we wrap the NullIdealStream in a /// IdealStreamLog, which prints out the method calls done on the stream /// to std::cerr. We also wrap the GroebnerInputIdealStream in a /// IdealStreamChecker which checks that we are correctly following the /// protocol of GroebnerInputIdealStream - that's only recommended when /// debugging as it is slow. /// /// GroebnerConfiguration configuration(101, 4); // mod 101, 4 variables /// GroebnerInputIdealStream input(configuration); /// IdealStreamChecker checked(input); /// checked.idealBegin(2); // describe ideal with 2 basis elements /// checked.appendPolynomial(2); // describe generator with 2 terms /// checked.appendTermBegin(); /// checked.appendExponent(0, 40); // x0^40 /// checked.appendTermDone(3); // 3 * x0^40 /// checked.appendTermBegin(); /// checked.appendExponent(1, 5); // x1^5 /// checked.appendExponent(2, 7); // x2^7 /// checked.appendTermDone(11); // 11 * x1^5 * x2^7 /// checked.appendPolynomialDone(); // 3 * x0^40 + 11 * x1^5 * x2^7 /// checked.appendPolynomialBegin(1); /// checked.appendTermBegin(); /// checked.appendTermDone(13); // 13 /// checked.appendPolynomialDone(); // 13 /// checked.idealDone(); // the generators are 3*x0^40 + 11*x1^5*x2^7 and 13 /// NullIdealStream nullStream; /// IdealStreamLog logStream(nullStream, std::cerr); /// computeGroebnerBasis(input, logStream); /// /// The ideal constructed on the passed-in GroebnerInputIdealStream will /// be cleared. If you need it again for something else, you will have /// to re-construct it. template void computeGroebnerBasis( GroebnerInputIdealStream& inputWhichWillBeCleared, OutputStream& output ); class NullIdealStream; /// Passes on all method calls to an inner ideal stream while printing out /// what methods get called to an std::ostream. template class IdealStreamLog { public: typedef GroebnerConfiguration::Coefficient Coefficient; typedef GroebnerConfiguration::VarIndex VarIndex; typedef GroebnerConfiguration::Exponent Exponent; typedef GroebnerConfiguration::Component Component; /// All calls are written to log and then passed on to stream. IdealStreamLog(std::ostream& log, Stream& stream); /// All calls are written to log. IdealStreamLog( std::ostream& log, Coefficient modulus, VarIndex varCount, Component comCount ); ~IdealStreamLog(); Coefficient modulus() const; VarIndex varCount() const; Component comCount() const; void idealBegin(); void idealBegin(size_t polyCount); void appendPolynomialBegin(); void appendPolynomialBegin(size_t termCount); void appendTermBegin(Component com); void appendExponent(VarIndex index, Exponent exponent); void appendTermDone(Coefficient coefficient); void appendPolynomialDone(); void idealDone(); private: const Coefficient mModulus; const VarIndex mVarCount; const Component mComCount; Stream* const mStream; std::ostream& mLog; }; /// An ideal stream that simply ignores all the method calls it receives. /// Can be handy in combination with IdealStreamLog or as a temporary /// stand-in if you have not yet written your own ideal stream. class NullIdealStream { public: typedef GroebnerConfiguration::Coefficient Coefficient; typedef GroebnerConfiguration::VarIndex VarIndex; typedef GroebnerConfiguration::Exponent Exponent; typedef GroebnerConfiguration::Component Component; NullIdealStream( Coefficient modulus, VarIndex varCount, Component comCount ); Coefficient modulus() const {return mModulus;} VarIndex varCount() const {return mVarCount;} Component comCount() const {return mComCount;} void idealBegin() {} void idealBegin(size_t polyCount) {} void appendPolynomialBegin() {} void appendPolynomialBegin(size_t termCount) {} void appendTermBegin(Component com) {} void appendExponent(VarIndex index, Exponent exponent) {} void appendTermDone(Coefficient coefficient) {} void appendPolynomialDone() {} void idealDone() {} private: const Coefficient mModulus; const VarIndex mVarCount; const Component mComCount; }; template void streamSimpleIdeal(OutputStream& output); namespace mgbi { // Not part of the public interface of MathicGB /// Class that checks to see if the protocol for an ideal stream is followed. /// A method will return false if that is not the case. This class is not /// itself an ideal stream - it is intended to be used with ideal streams for /// debugging. class StreamStateChecker { public: typedef GroebnerConfiguration::Coefficient Coefficient; typedef GroebnerConfiguration::VarIndex VarIndex; typedef GroebnerConfiguration::Exponent Exponent; typedef GroebnerConfiguration::Component Component; StreamStateChecker( const Coefficient modulus, const VarIndex varCount, const Component comCount ); ~StreamStateChecker(); void idealBegin(); void idealBegin(size_t polyCount); void appendPolynomialBegin(); void appendPolynomialBegin(size_t termCount); void appendTermBegin(Component com); void appendExponent(VarIndex index, Exponent exponent); void appendTermDone(Coefficient coefficient); void appendPolynomialDone(); void idealDone(); bool hasIdeal() const; private: struct Pimpl; Pimpl* const mPimpl; }; } /// Use this class to check that you are following the correct protocol /// for calling methods on an ideal stream. This has significant overhead /// so it is not recommended for production use. If you have built the /// MathicGB library in debug mode then this is already automatically /// used for GroebnerInputIdealStream. template class IdealStreamChecker { public: typedef GroebnerConfiguration::Coefficient Coefficient; typedef GroebnerConfiguration::VarIndex VarIndex; typedef GroebnerConfiguration::Exponent Exponent; typedef GroebnerConfiguration::Component Component; IdealStreamChecker(Stream& stream); Coefficient modulus() const; VarIndex varCount() const; Component comCount() const; void idealBegin(); void idealBegin(size_t polyCount); void appendPolynomialBegin(); void appendPolynomialBegin(size_t termCount); void appendTermBegin(Component com); void appendExponent(VarIndex index, Exponent exponent); void appendTermDone(Coefficient coefficient); void appendPolynomialDone(); void idealDone(); private: Stream& mStream; mgbi::StreamStateChecker mChecker; }; } // ******************************************************** // Nothing below this line is part of the public interface of MathicGB. #ifdef MATHICGB_DEBUG #include #endif namespace mgb { // ** Functions // This method is made inline to avoid the overhead from calling a function // for every exponent. This is also why mExponents is not inside the pimpl - // otherwise we couldn't access it from here. That then explains why // mExponents is a raw pointer instead of a std::vector - the compiler for the // caller and the library must agree on the memory layout of the object and // that is less likely to introduce problems for a raw pointer than for a // std::vector. In particular, doing it this way allows the library and // the caller to use different implementations of the STL. inline void GroebnerInputIdealStream::appendExponent( const VarIndex index, const Exponent exponent ) { #ifdef MATHICGB_DEBUG assert(index < varCount()); #endif mExponents[index] = exponent; } // ** Implementation of class GroebnerConfiguration // This code is inline so that things will still work even if // the caller uses a different implementation of std::vector than // the library does internally. So we have to decay objects of // type std::vector to pointers. inline bool GroebnerConfiguration::setMonomialOrder( const BaseOrder baseOrder, const std::vector& gradings ) { // We cannot do gradings.data() since we may be compiling without C++11 // support. We also cannot do &*gradings.begin() if gradings is empty // since then we are dereferencing an invalid iterator - the debug build // of MSVC's STL will correctly flag this as an error. const MonomialOrderData data = { baseOrder, gradings.empty() ? static_cast(0) : &*gradings.begin(), gradings.size() }; return setMonomialOrderInternal(data); } inline std::pair< GroebnerConfiguration::BaseOrder, std::vector > GroebnerConfiguration::monomialOrder() const { const MonomialOrderData data = monomialOrderInternal(); return std::make_pair( data.baseOrder, std::vector(data.gradings, data.gradings + data.gradingsSize) ); } inline GroebnerConfiguration::Callback::Action GroebnerConfiguration::callbackCaller(void* obj) { return static_cast(obj)->call(); }; inline void GroebnerConfiguration::setCallback(Callback* callback) { setCallbackInternal(static_cast(callback), callbackCaller); } inline const GroebnerConfiguration::Callback* GroebnerConfiguration::callback() const { return const_cast(*this).callback(); } inline GroebnerConfiguration::Callback* GroebnerConfiguration::callback() { return static_cast(callbackDataInternal()); } // ** Implementation of the class IdealStreamLog // This class has to be inline as it is a template. template IdealStreamLog::IdealStreamLog(std::ostream& log, Stream& stream): mModulus(stream.modulus()), mVarCount(stream.varCount()), mComCount(stream.comCount()), mStream(&stream), mLog(log) { mLog << "IdealStreamLog s(stream, log); // modulus=" << mModulus << ", varCount=" << mVarCount << ", comCount=" << mComCount << '\n'; } template IdealStreamLog::IdealStreamLog( std::ostream& log, Coefficient modulus, VarIndex varCount, Component comCount ): mModulus(modulus), mVarCount(varCount), mComCount(comCount), mStream(0), mLog(log) { mLog << "IdealStreamLog s(stream, " << mModulus << ", " << mVarCount << ", " << mComCount << ");\n"; } template IdealStreamLog::~IdealStreamLog() { mLog << "// s.~IdealStreamLog();\n"; } template typename IdealStreamLog::Coefficient IdealStreamLog::modulus() const { return mModulus; } template typename IdealStreamLog::VarIndex IdealStreamLog::varCount() const { return mVarCount; } template typename IdealStreamLog::Component IdealStreamLog::comCount() const { return mComCount; } template void IdealStreamLog::idealBegin() { mLog << "s.idealBegin();\n"; if (mStream != 0) mStream->idealBegin(); } template void IdealStreamLog::idealBegin(size_t polyCount) { mLog << "s.idealBegin(" << polyCount << "); // polyCount\n"; if (mStream != 0) mStream->idealBegin(polyCount); } template void IdealStreamLog::appendPolynomialBegin() { mLog << "s.appendPolynomialBegin();\n"; if (mStream != 0) mStream->appendPolynomialBegin(); } template void IdealStreamLog::appendPolynomialBegin(size_t termCount) { mLog << "s.appendPolynomialBegin(" << termCount << ");\n"; if (mStream != 0) mStream->appendPolynomialBegin(termCount); } template void IdealStreamLog::appendTermBegin(const Component com) { mLog << "s.appendTermBegin(" << com << ");\n"; if (mStream != 0) mStream->appendTermBegin(com); } template void IdealStreamLog::appendExponent(VarIndex index, Exponent exponent) { mLog << "s.appendExponent(" << index << ", " << exponent << "); // index, exponent\n"; if (mStream != 0) mStream->appendExponent(index, exponent); } template void IdealStreamLog::appendTermDone(Coefficient coefficient) { mLog << "s.appendTermDone(" << coefficient << "); // coefficient\n"; if (mStream != 0) mStream->appendTermDone(coefficient); } template void IdealStreamLog::appendPolynomialDone() { mLog << "s.appendPolynomialDone();\n"; if (mStream != 0) mStream->appendPolynomialDone(); } template void IdealStreamLog::idealDone() { mLog << "s.idealDone();\n"; if (mStream != 0) mStream->idealDone(); } // ** Implementation of the class IdealStreamChecker // This class has to be inline as it is a template. template IdealStreamChecker::IdealStreamChecker(Stream& stream): mStream(stream), mChecker(stream.modulus(), stream.varCount(), stream.comCount()) {} template typename IdealStreamChecker::Coefficient IdealStreamChecker::modulus() const { return mStream.modulus(); } template typename IdealStreamChecker::VarIndex IdealStreamChecker::varCount() const { return mStream.varCount(); } template typename IdealStreamChecker::Component IdealStreamChecker::comCount() const { return mStream.comCount(); } template void IdealStreamChecker::idealBegin() { mChecker.idealBegin(); mStream.idealBegin(); } template void IdealStreamChecker::idealBegin(size_t polyCount) { mChecker.idealBegin(polyCount); mStream.idealBegin(polyCount); } template void IdealStreamChecker::appendPolynomialBegin() { mChecker.appendPolynomialBegin(); mStream.appendPolynomialBegin(); } template void IdealStreamChecker::appendPolynomialBegin(size_t termCount) { mChecker.appendPolynomialBegin(termCount); mStream.appendPolynomialBegin(termCount); } template void IdealStreamChecker::appendTermBegin(const Component com) { mChecker.appendTermBegin(com); mStream.appendTermBegin(com); } template void IdealStreamChecker::appendExponent(VarIndex index, Exponent exponent) { mChecker.appendExponent(index, exponent); mStream.appendExponent(index, exponent); } template void IdealStreamChecker::appendTermDone(Coefficient coefficient) { mChecker.appendTermDone(coefficient); mStream.appendTermDone(coefficient); } template void IdealStreamChecker::appendPolynomialDone() { mChecker.appendPolynomialDone(); mStream.appendPolynomialDone(); } template void IdealStreamChecker::idealDone() { mChecker.idealDone(); mStream.idealDone(); } // ** Implementation of the class NullIdealStream // This class isn't a template, but it might become one and it is so // trivial that making it inline is not a big deal - it's not much more // than just its interface. The idea is also for this class to have minimal // overhead and making it inline helps with that. inline NullIdealStream::NullIdealStream( Coefficient modulus, VarIndex varCount, Component comCount ): mModulus(modulus), mVarCount(varCount), mComCount(comCount) {} namespace mgbi { /// Used to read an internal MathicGB ideal without exposing the type of /// the ideal. class IdealAdapter { public: typedef GroebnerConfiguration::Coefficient Coefficient; typedef GroebnerConfiguration::VarIndex VarIndex; typedef GroebnerConfiguration::Exponent Exponent; typedef GroebnerConfiguration::Component Component; typedef size_t PolyIndex; typedef size_t TermIndex; struct ConstTerm { Coefficient coef; const Exponent* exponents; Component com; }; IdealAdapter(); ~IdealAdapter(); VarIndex varCount() const; size_t polyCount() const; size_t termCount(PolyIndex poly) const; Component componentCount() const; /// Sets the internal position to the first term of the first polynomial. void toFirstTerm(); /// Returns the next term. First all terms of polynomial 0 are returned, /// then all terms of the next polynomial and so on. ConstTerm nextTerm() const; private: friend class mgbi::PimplOf; struct Pimpl; Pimpl* mPimpl; }; bool internalComputeGroebnerBasis( GroebnerInputIdealStream& inputWhichWillBeCleared, IdealAdapter& output ); } template void computeGroebnerBasis( GroebnerInputIdealStream& inputWhichWillBeCleared, OutputStream& output ) { typedef mgbi::IdealAdapter::ConstTerm ConstTerm; mgbi::IdealAdapter ideal; const bool doOutput = mgbi::internalComputeGroebnerBasis(inputWhichWillBeCleared, ideal); if (!doOutput) return; ideal.toFirstTerm(); const size_t varCount = ideal.varCount(); const size_t polyCount = ideal.polyCount(); output.idealBegin(polyCount); for (size_t polyIndex = 0; polyIndex < polyCount; ++polyIndex) { const size_t termCount = ideal.termCount(polyIndex); output.appendPolynomialBegin(termCount); for (size_t termIndex = 0; termIndex < termCount; ++termIndex) { const ConstTerm term = ideal.nextTerm(); output.appendTermBegin(term.com); for (size_t var = 0; var < varCount; ++var) output.appendExponent(var, term.exponents[var]); output.appendTermDone(term.coef); } output.appendPolynomialDone(); } output.idealDone(); } } #endif mathicgb-master/src/mathicgb/000077500000000000000000000000001311555162500164765ustar00rootroot00000000000000mathicgb-master/src/mathicgb/Atomic.hpp000077500000000000000000000370721311555162500204370ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_ATOMIC_GUARD #define MATHICGB_ATOMIC_GUARD // We need this include for std::memory_order even if we are not // using std::atomic. #include MATHICGB_NAMESPACE_BEGIN namespace AtomicInternal { /// Tells the compiler (not the CPU) to not reorder reads across this line. inline void compilerReadMemoryBarrier(); /// Tells the compiler (not the CPU) to not reorder writes across this line. inline void compilerWriteMemoryBarrier(); /// Tells the compiler (not the CPU) to not reorder reads and writes across /// this line. inline void compilerReadWriteMemoryBarrier(); /// Tells the CPU and also the compiler to not reorder reads and writes /// across this line. inline void cpuReadWriteMemoryBarrier(); /// Stores a variable with sequentially consistent ordering. The variable /// must be aligned and have a size such that aligned reads of that size /// are atomic. This requies a locked instruction like XHCG according to /// http://goo.gl/U8xTK . template void seqCstStore(const T value, T& ref); } #if defined(_MSC_VER) && defined(MATHICGB_USE_CUSTOM_ATOMIC_X86_X64) MATHICGB_NAMESPACE_END #include MATHICGB_NAMESPACE_BEGIN namespace AtomicInternal { template struct SeqCst {}; #ifdef MATHICGB_USE_CUSTOM_ATOMIC_4BYTE template struct SeqCst { static void store(const T value, T& ref) { _InterlockedExchange((volatile LONG*)&ref, (LONG)value); } }; #endif #ifdef MATHICGB_USE_CUSTOM_ATOMIC_8BYTE template struct SeqCst { static void store(const T value, T& ref) { _InterlockedExchange64((volatile _LONGLONG*)&ref, (_LONGLONG)value); } }; #endif inline void compilerReadMemoryBarrier() {_ReadBarrier();} inline void compilerWriteMemoryBarrier() {_WriteBarrier();} inline void compilerReadWriteMemoryBarrier() {_ReadWriteBarrier();} inline void cpuReadWriteMemoryBarrier() {MemoryBarrier();} template void seqCstStore(const T value, T& ref) {SeqCst::store(value, ref);} } #endif #if defined(__GNUC__) && defined(MATHICGB_USE_CUSTOM_ATOMIC_X86_X64) namespace AtomicInternal { inline void compilerReadMemoryBarrier() { // As far as I can tell there is no way to do a partial optimization // barrier on GCC, so we have to do the full barrier every time. compilerReadWriteMemoryBarrier(); } inline void compilerWriteMemoryBarrier() {compilerReadWriteMemoryBarrier();} inline void compilerReadWriteMemoryBarrier() { // As far as I can tell this is not documented to work, but it is the // only way to do this on GCC and it is what the Linux kernel does, so // that will have to be good enough. __asm__ __volatile__ ("" ::: "memory"); } inline void cpuReadWriteMemoryBarrier() {__sync_synchronize();} template void seqCstStore(const T value, T& ref) { const auto ptr = static_cast(&ref); while (!__sync_bool_compare_and_swap(ptr, *ptr, value)) {} } } #endif namespace AtomicInternal { #ifdef MATHICGB_USE_FAKE_ATOMIC // This class has the same interface as the actual custom atomic // class but it does absolutely no synchronization and it does not // constrain compiler optimizations in any way. The purpose of this class // is to enable it while running only a single thread to determine the // overhead imposed by the atomic operations. template class FakeAtomic { public: FakeAtomic(): mValue() {} FakeAtomic(T value): mValue(value) {} T load(const std::memory_order) const {return mValue;} void store(const T value, const std::memory_order order) {mValue = value;} private: T mValue; }; template struct ChooseAtomic { typedef FakeAtomic type; }; #else /// Class for deciding which implementation of atomic to use. The default is /// to use std::atomic which is a fine choice if std::atomic is implemented /// in a reasonable way by the standard library implementation you are using. template struct ChooseAtomic { typedef std::atomic type; }; #endif } #ifdef MATHICGB_USE_CUSTOM_ATOMIC_X86_X64 namespace AtomicInternal { /// Custom Atomic class for x86 and x64. Uses special compiler directives /// for barriers. Only instantiate this for sizes where aligned reads and /// writes are guaranteed to be atomic - this class only takes care of the /// ordering constraints using CPU and compiler fences. Since the directives /// to achieve this are coming from the compiler it is surprising that /// any compiler ships with a std::atomic that is worse than this - but /// that is very much the case. Though implementing atomic load and store /// is very little code, as you can see, it is quite tricky and took me /// a long time to understand everything well enough to actually know what /// those few lines of code should say. Perhaps compiler vendors have /// postponed fast atomics just because they want to focus on other things /// since it's not that easy to figure out how to do right (on that topic, /// bug reports on this code are welcome!). /// /// There are 5 kinds of reorderings that we are concerned with here. Let /// S,S' be stores and let L,L' be stores. Note that these short-hands may /// be idiosyncratic - feel free to find some standard terminology from /// some prominent source and fix this to reflect that. /// /// SS: Store-after-store: Reorder S,S' to S',S /// SL: Store-after-load: Reorder S,L to L,S /// LS: Load-after-store: Reorder L,S to S,L /// LL: Load-after-load: Reorder L,L' to L',L /// DLL: Dependent-load-after-load: As LL but L' depends on L. For example /// reordering the load of p->a to before the load of p is a DLL. /// /// The DEC Alpha processor will perform all of these reorderings in the /// absense of memory barriers telling it not to do that, including DLL. /// DLL can happen on DEC Alpha if p->a is cached locally while p is not. /// Then p will be loaded from memory while p->a is loaded from the cache, /// which is functionally identical to loading p->a before p since we may /// see a value of p->a from the past while we get an up to date value of p. /// This can happen even if the processor that stored p did a full memory /// barrier between storing p->a and storing p. /// /// Compilers will also perform all of these reorderings to optimize the /// code - even including DLL. DLL happens if the compiler guesses what /// the value of p is, loads p->a and then checks that the guess for p /// was correct. This directly causes p->a to be actually loaded before p. /// These kinds of optimizations turn up in profile-driven optimization. /// /// You can check this out here: /// http://en.wikipedia.org/wiki/Memory_ordering /// /// On x86 and x64 only SL is done by the CPU, so we need a CPU barrier to /// prevent that and nothing else. The compiler is free to perform all of /// these reorderings, so we need lots of compiler optimization barriers /// to deal with all of these cases. /// /// Some of the quotes below are from: /// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1525.htm /// /// Also interesting: ///http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/ template class CustomAtomicX86X64 { public: CustomAtomicX86X64(): mValue() {} CustomAtomicX86X64(T value): mValue(value) {} MATHICGB_INLINE T load(const std::memory_order order) const { switch (order) { case std::memory_order_relaxed: // There are two constraints for memory_order_relaxed. The first // constraint is that if you read *p, then you will never // after that read a value of *p that was stored before the value // you just read, where "before" is in terms of either the same thread // that did the writing or external synchronization of another thread // with this thread. This is automaticaly guaranteed on this platform // and the compiler cannot break this guarantee. // // The second constraint is that writes performed by other threads will // appear "in a timely manner" when reading the written-to memory // location. It is not clear how much time is allowed to elapse before // this constraint is broken, but clearly the written value must turn // up eventually. This constraint could be broken in cases like this: // // while (x.load(std::memory_order_relaxed) == 0) { // // do something that does not write to x // } // // The problem is that the compiler might observe that x is not being // written to inside the loop, so the expression x.load(...) should be // the value for every iteration, so the code can safely be transformed // to: // // if (x.load(std::memory_order_relaxed) == 0) { // while (true) { // // ... // } // } // // So we need to tell the compiler that the value can change due to // code not in view of the current thread of execution. There are two // solutions that I have considered: // // * A compiler read memory barrier. This is overkill because it stops // the compiler from moving all reads across this line. // // * A volatile read. This is pretty much exactly what we need on gcc, // but on MSVC it provides extra guarantees that we do not need here: // http://msdn.microsoft.com/en-us/library/12a04hfd%28v=vs.80%29.aspx // // I do not think there is any best choice on MSVC, so I went for a // volatile read since it is the best choice on GCC. return const_cast(mValue); case std::memory_order_consume: { // Loads in this thread that depend on the loaded value must not be // reordered to before this load. So no DLL reorderings past this // load from after to before (up). So we need a read barrier AFTER the // load. It is a compiler only barrier since x86 and x64 CPUs do not do // DLL reorderings. const auto value = mValue; compilerReadMemoryBarrier(); return value; } case std::memory_order_acquire: { // Loads in this thread must not be reordered to before this load. // So no LL reorderings past this load from after to before (up). // So we need a read barrier AFTER the load. It is a compiler only // barrier since x86 and x64 CPUs do not do LL reorderings. const auto value = mValue; compilerReadMemoryBarrier(); return value; } case std::memory_order_seq_cst: { // There must be some global order in which all sequentially consistent // atomic operations are considered to have happened in. On x86 and x64 // this is guaranteed by just a normal read as long as all writes use // locked instructions like XHCG. See: http://goo.gl/U8xTK // // We still need to prevent the compiler from reordering the reads, // which is the same constraint as for std::memory_order_acquire. const auto value = mValue; compilerReadMemoryBarrier(); return value; } case std::memory_order_release: // not available for load case std::memory_order_acq_rel: // not available for load default: // specified value is not a known std::memory_order MATHICGB_UNREACHABLE; } } MATHICGB_INLINE void store(const T value, const std::memory_order order) { switch (order) { case std::memory_order_relaxed: // There are no reordering constraints here but we need to tell the // compiler that it must actually write out the value to memory in // a scenario like this: // // x.store(1, std::memory_order_relaxed); // while (true) {} // // So as for relaxed store we need either a volatile access or a memory // barrier. I chose a volatile access for the same reason as for the // store: MSVC has no best choice and for GCC the volatile is perfect. const_cast(mValue) = value; break; case std::memory_order_release: // Stores in this thread must not be reordered to after this store. // So no SS reorderings past this load from before to after (down). // So we need a barrier BEFORE the load. It is a compiler only barrier // since x86 and x64 CPUs do not do SS reorderings. compilerWriteMemoryBarrier(); mValue = value; break; case std::memory_order_acq_rel: // Combine the guarantees for std::memory_order_acquire and // std::memory_order_release. So no loads moved up past here (SL) and // no stores moved down past here (LL). We need a compiler barrier // BEFORE the load to avoid LL and a CPU (+compiler) barrier AFTER the // load to avoid SL, since x86 and x64 CPUs can in fact do SL // reordering. compilerWriteMemoryBarrier(); mValue = value; cpuReadWriteMemoryBarrier(); break; case std::memory_order_seq_cst: // All operations happen in a globally consistent total order. seqCstStore(value, mValue); break; case std::memory_order_consume: // not available for store case std::memory_order_acquire: // not available for store default: // specified value is not a known std::memory_order MATHICGB_UNREACHABLE; } } private: T mValue; }; #ifdef MATHICGB_USE_CUSTOM_ATOMIC_4BYTE template struct ChooseAtomic { typedef CustomAtomicX86X64 type; }; #endif #ifdef MATHICGB_USE_CUSTOM_ATOMIC_8BYTE template struct ChooseAtomic { typedef CustomAtomicX86X64 type; }; #endif } #endif /// This class is equivalent to std::atomic. Some functions from the /// interface of std::atomic are missing - add them as necessary. Do not add /// operator= and operator T() --- it is better to make the code explicit /// about when and how loading and storing of atomic variables occurs. /// /// The purpose of the class is that it performs far better than /// std::atomic for some implementations. For example the std::atomic in MSVC /// 2012 performs a compare-and-swap operation on a load even with the /// paramter std::memory_order_relaxed. /// /// We force all the functions to be inline because they can contain switches /// on the value of std::memory_order. This will usually be a compile-time /// constant parameter so that after inlining the switch will disappear. Yet /// the code size of the switch may make some compilers avoid the inline. template class Atomic { public: Atomic(): mValue() {} Atomic(T value): mValue(value) {} MATHICGB_INLINE T load(const std::memory_order order = std::memory_order_seq_cst) const { MATHICGB_ASSERT(debugAligned()); return mValue.load(order); } MATHICGB_INLINE void store( const T value, const std::memory_order order = std::memory_order_seq_cst ) { MATHICGB_ASSERT(debugAligned()); mValue.store(value, order); } private: Atomic(const Atomic&); // not available void operator=(const Atomic&); // not available bool debugAligned() const { return reinterpret_cast(&mValue) % sizeof(T) == 0; } typename AtomicInternal::ChooseAtomic::type mValue; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/Basis.cpp000077500000000000000000000015241311555162500202500ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "Basis.hpp" #include "PolyRing.hpp" #include "Poly.hpp" #include "MathicIO.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN void Basis::insert(std::unique_ptr&& p) { MATHICGB_ASSERT(p.get() != 0); MATHICGB_ASSERT(p->termsAreInDescendingOrder()); mGenerators.push_back(std::move(p)); } void Basis::sort() { const auto& monoid = ring().monoid(); const auto cmp = [&monoid]( const std::unique_ptr& a, const std::unique_ptr& b ) { return monoid.lessThan(a->leadMono(), b->leadMono()); }; std::sort(mGenerators.begin(), mGenerators.end(), cmp); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/Basis.hpp000077500000000000000000000025511311555162500202560ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_BASIS_GUARD #define MATHICGB_BASIS_GUARD #include "Poly.hpp" #include "PolyRing.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN class Poly; /// A collection of polynomials. @todo: replace with just std::vector. // Really: a list of polynomials // BUT ALSO maybe: includes memory areas for the polynomials? class Basis { public: Basis(const PolyRing &R) : mRing(R) {} Basis(Basis&& basis): mRing(basis.ring()), mGenerators(std::move(basis.mGenerators)) {} void insert(std::unique_ptr&& p); const PolyRing& ring() const { return mRing; } const PolyRing *getPolyRing() const { return &mRing; } const std::vector< std::unique_ptr>& viewGenerators() { return mGenerators; } const Poly *getPoly(size_t i) const { MATHICGB_ASSERT(i < size()); return mGenerators[i].get(); } size_t size() const {return mGenerators.size();} bool empty() const {return mGenerators.empty();} void reserve(size_t size) {mGenerators.reserve(size);} void sort(); private: Basis(const Basis&); // not available const PolyRing& mRing; std::vector< std::unique_ptr> mGenerators; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/CFile.cpp000077500000000000000000000014011311555162500201630ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "CFile.hpp" #include #include MATHICGB_NAMESPACE_BEGIN CFile::CFile(const std::string& fileName, const char* mode, NoThrowTag): mFile(fopen(fileName.c_str(), mode) ) {} CFile::CFile(const std::string& fileName, const char* mode): mFile(fopen(fileName.c_str(), mode) ) { if (mFile == 0) { std::ostringstream error; error << "Could not open file " << fileName << " in mode " << mode << '.'; mathic::reportError(error.str()); } } CFile::~CFile() { close(); } void CFile::close() { if (mFile != 0) fclose(mFile); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/CFile.hpp000077500000000000000000000024201311555162500201720ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_C_FILE_GUARD #define MATHICGB_C_FILE_GUARD #include #include MATHICGB_NAMESPACE_BEGIN /// RAII handle for a C FILE*. /// /// The purpose of using the C IO interface instead of iostreams is that the /// former is faster to a ridiculous degree. This class wraps the C IO /// interface to be more useful in a C++ context. For example the file is /// automatically closed in the destructor and if the file cannot be opened /// then an exception is thrown instead of returning a null pointer. class CFile { public: struct NoThrowTag {}; /// Sets the handle to null if the file cannot be opened - does not /// throw an exception. The purpose of the NoTrowTag parameter is only /// to indicate that no exception should be thrown on error. CFile(const std::string& fileName, const char* mode, NoThrowTag); /// Opens the file and throws an exception if the file cannot be opened. CFile(const std::string& fileName, const char* mode); ~CFile(); bool hasFile() const {return mFile != 0;} FILE* handle() {return mFile;} void close(); private: FILE* mFile; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ClassicGBAlg.cpp000077500000000000000000000540051311555162500214270ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ClassicGBAlg.hpp" #include "Reducer.hpp" #include "SPairs.hpp" #include "PolyBasis.hpp" #include "Basis.hpp" #include "LogDomain.hpp" #include "MathicIO.hpp" #include #include #include #include MATHICGB_DEFINE_LOG_DOMAIN( SPairDegree, "Displays the degree of the S-pairs being considered in " "Buchberger's algorithm." ); MATHICGB_DEFINE_LOG_DOMAIN( GBInsert, "Outputs polynomials that are inserted into the current " "basis during Groebner basis computation using Buchberger's. " "algorithm." ); MATHICGB_NAMESPACE_BEGIN /// Calculates a classic Grobner basis using Buchberger's algorithm. class ClassicGBAlg { public: ClassicGBAlg( const Basis& basis, Reducer& reducer, int monoLookupType, bool preferSparseReducers, size_t queueType ); // Replaces the current basis with a Grobner basis of the same ideal. void computeGrobnerBasis(); // How many S-pairs were not eliminated before reduction of the // corresponding S-polynomial. unsigned long long sPolyReductionCount() const {return mSPolyReductionCount;} // Returns the current basis. PolyBasis& basis() {return mBasis;} // Shows statistics on what the algorithm has done. void printStats(std::ostream& out) const; void printMemoryUse(std::ostream& out) const; size_t getMemoryUse() const; void setBreakAfter(unsigned int elements) { mBreakAfter = elements; } void setPrintInterval(unsigned int reductions) { mPrintInterval = reductions; } /// A value of zero means to let the algorithm decide a reasonable /// value based on the other settings. void setSPairGroupSize(unsigned int groupSize); void setReducerMemoryQuantum(size_t memoryQuantum) { mReducer.setMemoryQuantum(memoryQuantum); } void setUseAutoTopReduction(bool value) { mUseAutoTopReduction = value; } void setUseAutoTailReduction(bool value) { mUseAutoTailReduction = value; } /// callback is called every once in a while and then it has the /// option of stopping the computation. callback can be null, in /// which case no call is made and the computation continues. void setCallback(std::function callback) { mCallback = std::move(callback); } private: std::function mCallback; unsigned int mBreakAfter; unsigned int mPrintInterval; unsigned int mSPairGroupSize; bool mUseAutoTopReduction; bool mUseAutoTailReduction; // Perform a step of the algorithm. void step(); void autoTailReduce(); void insertReducedPoly(std::unique_ptr poly); // clears polynomials. void insertPolys(std::vector >& polynomials); const PolyRing& mRing; Reducer& mReducer; PolyBasis mBasis; SPairs mSPairs; mic::Timer mTimer; unsigned long long mSPolyReductionCount; }; ClassicGBAlg::ClassicGBAlg( const Basis& basis, Reducer& reducer, int monoLookupType, bool preferSparseReducers, size_t queueType ): mCallback(nullptr), mBreakAfter(0), mPrintInterval(0), mSPairGroupSize(reducer.preferredSetSize()), mUseAutoTopReduction(true), mUseAutoTailReduction(false), mRing(*basis.getPolyRing()), mReducer(reducer), mBasis(mRing, MonoLookup::makeFactory( basis.getPolyRing()->monoid(), monoLookupType )->make(preferSparseReducers, true) ), mSPairs(mBasis, preferSparseReducers), mSPolyReductionCount(0) { // Reduce and insert the generators of the ideal into the starting basis size_t const basisSize = basis.size(); std::vector > polys; for (size_t gen = 0; gen != basisSize; ++gen) polys.push_back(make_unique(*basis.getPoly(gen))); insertPolys(polys); } void ClassicGBAlg::setSPairGroupSize(unsigned int groupSize) { if (groupSize == 0) groupSize = mReducer.preferredSetSize(); else mSPairGroupSize = groupSize; } void ClassicGBAlg::insertPolys( std::vector >& polynomials ) { if (!mUseAutoTopReduction) { for (auto it = polynomials.begin(); it != polynomials.end(); ++it) { MATHICGB_ASSERT(it->get() != 0); if ((*it)->isZero()) continue; if (mBasis.divisor((*it)->leadMono()) != static_cast(-1)) { *it = mReducer.classicReduce(**it, mBasis); if ((*it)->isZero()) continue; } mBasis.insert(std::move(*it)); mSPairs.addPairs(mBasis.size() - 1); } polynomials.clear(); return; } std::vector toRetire; std::vector> toReduce; std::vector> toInsert; std::swap(toInsert, polynomials); while (!toInsert.empty()) { // todo: sort by lead term to avoid insert followed by immediate // removal. // insert polynomials from toInsert with minimal lead term and // extract those from the basis that become non-minimal. for (auto it = toInsert.begin(); it != toInsert.end(); ++it) { MATHICGB_ASSERT(it->get() != 0); if ((*it)->isZero()) continue; // We check for a divisor from mBasis because a new reducer // might have been added since we did the reduction or perhaps a // non-reduced polynomial was passed in. if (mBasis.divisor((*it)->leadMono()) != static_cast(-1)) toReduce.push_back(std::move(*it)); else { MATHICGB_IF_STREAM_LOG(GBInsert) { stream << "Inserting basis element " << mBasis.size() << ": "; MathicIO<>().writePoly(**it, true, stream); stream << '\n'; }; mBasis.insert(std::move(*it)); MATHICGB_ASSERT(toRetire.empty()); mSPairs.addPairsAssumeAutoReduce(mBasis.size() - 1, toRetire); for (auto r = toRetire.begin(); r != toRetire.end(); ++r) toReduce.push_back(mBasis.retire(*r)); toRetire.clear(); } } toInsert.clear(); MATHICGB_ASSERT(toRetire.empty()); // reduce everything in toReduce if (!toReduce.empty()) { mReducer.classicReducePolySet(toReduce, mBasis, toInsert); toReduce.clear(); } } MATHICGB_ASSERT(toRetire.empty()); MATHICGB_ASSERT(toInsert.empty()); MATHICGB_ASSERT(toReduce.empty()); } void ClassicGBAlg::insertReducedPoly( std::unique_ptr polyToInsert ) { MATHICGB_ASSERT(polyToInsert.get() != 0); if (polyToInsert->isZero()) return; MATHICGB_ASSERT(mBasis.divisor(polyToInsert->leadMono()) == static_cast(-1)); if (tracingLevel > 20) { std::cerr << "inserting basis element " << mBasis.size() << ": "; if (tracingLevel > 100) { MathicIO<>().writePoly(*polyToInsert, false, std::cerr); std::cerr << std::endl; } else { mRing.printMonomialFrobbyM2Format (std::cerr, Monoid::toOld(polyToInsert->leadMono())); if (polyToInsert->termCount() > 1) std::cerr << " + [...]"; std::cerr << std::endl; } } if (!mUseAutoTopReduction) { size_t const newGen = mBasis.size(); mBasis.insert(std::move(polyToInsert)); mSPairs.addPairs(newGen); return; } std::vector toRetireAndReduce; std::vector toReduce; try { do { // reduce polynomial and insert into basis { std::unique_ptr reduced; if (toReduce.empty()) // if first iteration reduced = std::move(polyToInsert); else { reduced = mReducer.classicReduce(*toReduce.back(), mBasis); if (tracingLevel > 20) { if (reduced->isZero()) { std::cerr << "auto-top-reduce cascade: " "basis element reduced to zero." << std::endl; } else { std::cerr << "auto-top-reduce cascade: " "inserting reduced poly with lead term " << std::endl; mRing.printMonomialFrobbyM2Format (std::cerr, Monoid::toOld(reduced->leadMono())); std::cerr << '\n'; } } delete toReduce.back(); toReduce.pop_back(); } if (reduced->isZero()) continue; reduced->makeMonic(); mBasis.insert(std::move(reduced)); } // form S-pairs and retire basis elements that become top reducible. const size_t newGen = mBasis.size() - 1; MATHICGB_ASSERT(toRetireAndReduce.empty()); mSPairs.addPairsAssumeAutoReduce(newGen, toRetireAndReduce); for (std::vector::const_iterator it = toRetireAndReduce.begin(); it != toRetireAndReduce.end(); ++it) { toReduce.push_back(0); // allocate space in vector before .release() toReduce.back() = mBasis.retire(*it).release(); } toRetireAndReduce.clear(); } while (!toReduce.empty()); } catch (...) { for (std::vector::iterator it = toReduce.begin(); it != toReduce.end(); ++it) delete *it; throw; } MATHICGB_ASSERT(toReduce.empty()); MATHICGB_ASSERT(toRetireAndReduce.empty()); } void ClassicGBAlg::computeGrobnerBasis() { size_t counter = 0; mTimer.reset(); if (mUseAutoTailReduction) autoTailReduce(); while (!mSPairs.empty()) { if (mCallback != nullptr && !mCallback()) break; step(); if (mBreakAfter != 0 && mBasis.size() > mBreakAfter) { std::cerr << "Stopping Grobner basis computation due to reaching limit of " << mBreakAfter << " basis elements." << std::endl; break; } if (mPrintInterval != 0 && (++counter % mPrintInterval) == 0) printStats(std::cerr); } if (mPrintInterval != 0) printStats(std::cerr); //mReducer->dump(); /* for (size_t i = 0; i < mBasis.size(); ++i) if (!mBasis.retired(i)) mBasis.replaceSameLeadTerm (i, mReducer->classicTailReduce(mBasis.poly(i), mBasis)); */ } void ClassicGBAlg::step() { MATHICGB_ASSERT(!mSPairs.empty()); if (tracingLevel > 30) std::cerr << "Determining next S-pair" << std::endl; MATHICGB_ASSERT(mSPairGroupSize >= 1); std::vector > spairGroup; exponent w = 0; for (unsigned int i = 0; i < mSPairGroupSize; ++i) { auto p = mSPairs.pop(w); if (p.first == static_cast(-1)) { MATHICGB_ASSERT(p.second == static_cast(-1)); break; // no more S-pairs } MATHICGB_ASSERT(p.first != static_cast(-1)); MATHICGB_ASSERT(p.second != static_cast(-1)); MATHICGB_ASSERT(!mBasis.retired(p.first)); MATHICGB_ASSERT(!mBasis.retired(p.second)); spairGroup.push_back(p); } if (spairGroup.empty()) return; // no more s-pairs std::vector> reduced; // w is the negative of the degree of the lcm's of the chosen spairs MATHICGB_LOG(SPairDegree) << spairGroup.size() << " pairs in degree " << -w << std::endl; mReducer.classicReduceSPolySet(spairGroup, mBasis, reduced); // sort the elements to get deterministic behavior. The order will change // arbitrarily when running multithreaded. Also, if preferring older // reducers, it is of benefit to break ties by preferring the sparser // reducer. Age does not have ties, since each element has a distinct // index, but if they all come from the same matrix then there is // really nothing to distinguish them - the relative age is arbitrarily // chosen. If we order sparsest-first, we will effectively make the // arbitrary choice among reducers from the same matrix in favor of sparser // reducers. auto order = [&]( const std::unique_ptr& a, const std::unique_ptr& b ) { const auto aTermCount = a->termCount(); const auto bTermCount = b->termCount(); if (aTermCount < bTermCount) return true; if (aTermCount > bTermCount) return false; auto bIt = b->begin(); const auto aEnd = a->end(); for (auto aIt = a->begin(); aIt != aEnd; ++aIt, ++bIt) { const auto monoCmp = mRing.monoid().compare(aIt.mono(), bIt.mono()); if (monoCmp == LT) return true; if (monoCmp == GT) return false; if (aIt.coef() < bIt.coef()) return true; if (aIt.coef() > bIt.coef()) return false; } return false; }; std::sort(reduced.begin(), reduced.end(), order); insertPolys(reduced); if (mUseAutoTailReduction) autoTailReduce(); } void ClassicGBAlg::autoTailReduce() { MATHICGB_ASSERT(mUseAutoTailReduction); for (size_t i = 0; i < mBasis.size(); ++i) { if (mBasis.retired(i)) continue; if (mBasis.usedAsReducerCount(i) < 1000) continue; mBasis.replaceSameLeadTerm (i, mReducer.classicTailReduce(mBasis.poly(i), mBasis)); } } size_t ClassicGBAlg::getMemoryUse() const { return mBasis.getMemoryUse() + mRing.getMemoryUse() + mReducer.getMemoryUse() + mSPairs.getMemoryUse(); } void ClassicGBAlg::printStats(std::ostream& out) const { out << " reduction type: " << mReducer.description() << '\n'; out << " divisor tab type: " << mBasis.monoLookup().getName() << '\n'; out << " S-pair queue type: " << mSPairs.name() << '\n'; out << " total compute time: " << mTimer.getMilliseconds()/1000.0 << " seconds " << '\n'; out << " S-pair group size: " << mSPairGroupSize << '\n'; mic::ColumnPrinter pr; pr.addColumn(true, " "); pr.addColumn(false, " "); pr.addColumn(true, " "); std::ostream& name = pr[0]; std::ostream& value = pr[1]; std::ostream& extra = pr[2]; const size_t basisSize = mBasis.size(); const double mseconds = mTimer.getMilliseconds(); const size_t pending = mSPairs.pairCount(); name << "Time spent:\n"; value << mTimer << '\n'; extra << mic::ColumnPrinter::oneDecimal(mseconds / basisSize) << " ms per basis element\n"; const double pendingRatio = static_cast(pending) / basisSize; name << "Basis elements:\n"; value << mic::ColumnPrinter::commafy(basisSize) << '\n'; extra << mic::ColumnPrinter::oneDecimal(pendingRatio) << " Sp pend per basis ele\n"; const size_t basisTermCount = mBasis.monomialCount(); name << "Terms for basis:\n"; value << mic::ColumnPrinter::commafy(basisTermCount) << '\n'; extra << mic::ColumnPrinter::ratioInteger(basisTermCount, basisSize) << " terms per basis ele\n"; const size_t minLeadCount = mBasis.minimalLeadCount(); name << "Minimum lead terms:\n"; value << mic::ColumnPrinter::commafy(minLeadCount) << '\n'; extra << mic::ColumnPrinter::percentInteger(minLeadCount, basisSize) << " basis ele have min lead\n"; const size_t lastMinLead = mBasis.maxIndexMinimalLead() + 1; const size_t timeSinceLastMinLead = basisSize - lastMinLead; name << "Index of last min lead:\n"; value << mic::ColumnPrinter::commafy(lastMinLead) << '\n'; extra << mic::ColumnPrinter::percentInteger(timeSinceLastMinLead, basisSize) << " of basis added since then\n"; const unsigned long long considered = mBasis.size() * (mBasis.size() - 1) / 2; name << "S-pairs considered:\n"; value << mic::ColumnPrinter::commafy(considered) << '\n'; extra << '\n'; name << "S-pairs pending:\n"; value << mic::ColumnPrinter::commafy(pending) << '\n'; extra << mic::ColumnPrinter::percentInteger(pending, considered) << " of considered\n"; unsigned long long const reductions = sPolyReductionCount(); name << "S-pairs reduced:\n"; value << mic::ColumnPrinter::commafy(reductions) << '\n'; extra << '\n'; //Reducer::Stats reducerStats = mReducer.sigStats(); SPairs::Stats sPairStats = mSPairs.stats(); unsigned long long const primeElim = sPairStats.relativelyPrimeHits; name << "Rel.prime sp eliminated:\n"; value << mic::ColumnPrinter::commafy(primeElim) << '\n'; extra << mic::ColumnPrinter::percentInteger(primeElim, reductions) << " of late eliminations\n"; /*const unsigned long long singularReductions = reducerStats.singularReductions; name << "Singular reductions:\n"; value << mic::ColumnPrinter::commafy(singularReductions) << '\n'; extra << mic::ColumnPrinter::percentInteger(singularReductions, reductions) << " of reductions\n";*/ /*const unsigned long long zeroReductions = reducerStats.zeroReductions; name << "Reductions to zero:\n"; value << mic::ColumnPrinter::commafy(zeroReductions) << '\n'; extra << mic::ColumnPrinter::percentInteger(zeroReductions, reductions) << " of reductions\n";*/ /*const unsigned long long newReductions = reductions - singularReductions - zeroReductions; name << "Reductions to new ele:\n"; value << mic::ColumnPrinter::commafy(newReductions) << '\n'; extra << mic::ColumnPrinter::percentInteger(newReductions, reductions) << " of reductions\n";*/ /*const unsigned long long redSteps = reducerStats.steps; name << "Sig reduction steps:\n"; value << mic::ColumnPrinter::commafy(redSteps) << '\n'; extra << mic::ColumnPrinter::ratioInteger (redSteps, reductions - singularReductions) << " steps per non-sing reduction\n";*/ /*const unsigned long long longestReduction = reducerStats.maxSteps; name << "Longest sig reduction:\n"; value << mic::ColumnPrinter::commafy(longestReduction) << '\n'; extra << '\n';*/ /*Reducer::Stats classicRedStats = mReducer.classicStats(); const unsigned long long clReductions = classicRedStats.reductions; name << "Classic reductions:\n"; value << mic::ColumnPrinter::commafy(clReductions) << '\n'; extra << '\n';*/ /*const unsigned long long clRedSteps = classicRedStats.steps; const double clStepsRatio = static_cast(clRedSteps) / clReductions; name << "Classic reduction steps:\n"; value << mic::ColumnPrinter::commafy(clRedSteps) << '\n'; extra << mic::ColumnPrinter::ratioInteger(clRedSteps, clReductions) << " steps per reduction\n";*/ /*const unsigned long long clLongestReduction = classicRedStats.maxSteps; name << "Longest classic red:\n"; value << mic::ColumnPrinter::commafy(clLongestReduction) << '\n'; extra << '\n';*/ //SPairs::Stats sPairStats = mSPairs.stats(); unsigned long long marginal = sPairStats.sPairsConsidered; unsigned long long const primeHits = sPairStats.relativelyPrimeHits; name << "Buchb relatively prime:\n"; value << mic::ColumnPrinter::commafy(primeHits) << '\n'; extra << mic::ColumnPrinter::percentInteger(primeHits, marginal) << " of S-pairs\n"; marginal -= primeHits; unsigned long long const simpleHits = sPairStats.buchbergerLcmSimpleHits; name << "Buchb lcm simple hits:\n"; value << mic::ColumnPrinter::commafy(simpleHits) << '\n'; extra << mic::ColumnPrinter::percentInteger(simpleHits, marginal) << " of remaining S-pairs\n"; marginal -= simpleHits; unsigned long long const simpleHitsLate = sPairStats.buchbergerLcmSimpleHitsLate; name << "Buchb late lcm simple hits:\n"; value << mic::ColumnPrinter::commafy(simpleHitsLate) << '\n'; extra << mic::ColumnPrinter::percentInteger(simpleHitsLate, marginal) << " of remaining S-pairs\n"; marginal -= simpleHitsLate; unsigned long long const buchAdvHits = sPairStats.buchbergerLcmAdvancedHits; name << "Buchb lcm adv hits:\n"; value << mic::ColumnPrinter::commafy(buchAdvHits) << '\n'; extra << mic::ColumnPrinter::percentInteger(buchAdvHits, marginal) << " of remaining S-pairs\n"; const unsigned long long buchCache = sPairStats.buchbergerLcmCacheHits; name << "Buchb lcm cache hits:\n"; value << mic::ColumnPrinter::commafy(buchCache) << '\n'; extra << mic::ColumnPrinter::percentInteger(buchCache, simpleHits) << " of simple hits\n"; const unsigned long long buchCacheLate = sPairStats.buchbergerLcmCacheHitsLate; name << "Buchb late lcm cache hits:\n"; value << mic::ColumnPrinter::commafy(buchCacheLate) << '\n'; extra << mic::ColumnPrinter::percentInteger(buchCacheLate, simpleHits) << " of simple hits\n"; out << "***** Classic Buchberger algorithm statistics *****\n" << pr << std::flush; } void ClassicGBAlg::printMemoryUse(std::ostream& out) const { // Set up printer mic::ColumnPrinter pr; pr.addColumn(); pr.addColumn(false); pr.addColumn(false); std::ostream& name = pr[0]; std::ostream& value = pr[1]; std::ostream& extra = pr[2]; const size_t total = getMemoryUse(); { // Grobner basis const size_t basisMem = mBasis.getMemoryUse(); name << "Grobner basis:\n"; value << mic::ColumnPrinter::bytesInUnit(basisMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(basisMem, total) << '\n'; } { // Spairs const size_t sPairMem = mSPairs.getMemoryUse(); name << "S-pairs:\n"; value << mic::ColumnPrinter::bytesInUnit(sPairMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(sPairMem, total) << '\n'; } { // Reducer const size_t reducerMem = mReducer.getMemoryUse(); name << "Reducer:\n"; value << mic::ColumnPrinter::bytesInUnit(reducerMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(reducerMem, total) << '\n'; } { // Signatures const size_t sigMem = mRing.getMemoryUse(); name << "Monomials:\n"; value << mic::ColumnPrinter::bytesInUnit(sigMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(sigMem, total) << '\n'; } // total name << "-------------\n"; value << '\n'; extra << '\n'; name << "Memory used in total:\n"; value << mic::ColumnPrinter::bytesInUnit(total) << "\n"; extra << "\n"; out << "*** Memory use by component ***\n" << pr << std::flush; } Basis computeGBClassicAlg( Basis&& inputBasis, ClassicGBAlgParams params ) { ClassicGBAlg alg( inputBasis, *params.reducer, params.monoLookupType, params.preferSparseReducers, params.sPairQueueType ); alg.setBreakAfter(params.breakAfter); alg.setPrintInterval(params.printInterval); alg.setSPairGroupSize(params.sPairGroupSize); alg.setReducerMemoryQuantum(params.reducerMemoryQuantum); alg.setUseAutoTopReduction(params.useAutoTopReduction); alg.setUseAutoTailReduction(params.useAutoTailReduction); alg.setCallback(params.callback); alg.computeGrobnerBasis(); return std::move(*alg.basis().toBasisAndRetireAll()); } Basis computeModuleGBClassicAlg( Basis&& inputBasis, ClassicGBAlgParams params ) { return computeGBClassicAlg(std::move(inputBasis), params); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ClassicGBAlg.hpp000077500000000000000000000015011311555162500214250ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_CLASSIC_GB_ALG_GUARD #define MATHICGB_CLASSIC_GB_ALG_GUARD #include MATHICGB_NAMESPACE_BEGIN class Reducer; class Basis; struct ClassicGBAlgParams { Reducer* reducer; int monoLookupType; bool preferSparseReducers; size_t sPairQueueType; unsigned int breakAfter; unsigned int printInterval; unsigned int sPairGroupSize; size_t reducerMemoryQuantum; bool useAutoTopReduction; bool useAutoTailReduction; std::function callback; }; Basis computeGBClassicAlg(Basis&& inputBasis, ClassicGBAlgParams params); Basis computeModuleGBClassicAlg(Basis&& inputBasis, ClassicGBAlgParams params); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/F4MatrixBuilder.cpp000077500000000000000000000301441311555162500221540ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "F4MatrixBuilder.hpp" #include "LogDomain.hpp" MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixBuild, "Displays statistics about F4 matrix construction." ); MATHICGB_NAMESPACE_BEGIN MATHICGB_NO_INLINE auto F4MatrixBuilder::findOrCreateColumn( ConstMonoRef monoA, ConstMonoRef monoB, TaskFeeder& feeder ) -> std::pair { const auto col = ColReader(mMap).findProduct(monoA, monoB); if (col.first != 0) return std::make_pair(*col.first, *col.second); return createColumn(monoA, monoB, feeder); } MATHICGB_INLINE auto F4MatrixBuilder::findOrCreateColumn( ConstMonoRef monoA, ConstMonoRef monoB, const ColReader& colMap, TaskFeeder& feeder ) -> std::pair { const auto col = colMap.findProduct(monoA, monoB); if (col.first == 0) return findOrCreateColumn(monoA, monoB, feeder); return std::make_pair(*col.first, *col.second); } MATHICGB_NO_INLINE void F4MatrixBuilder::createTwoColumns( ConstMonoRef monoA1, ConstMonoRef monoA2, ConstMonoRef monoB, TaskFeeder& feeder ) { createColumn(monoA1, monoB, feeder); createColumn(monoA2, monoB, feeder); } F4MatrixBuilder::F4MatrixBuilder( const PolyBasis& basis, const size_t memoryQuantum ): mTmp(basis.ring().monoid().alloc()), mBasis(basis), mMap(basis.ring()), mMonomialsLeft(), mMonomialsRight(), mBuilder(basis.ring(), mMap, mMonomialsLeft, mMonomialsRight, memoryQuantum), mLeftColCount(0), mRightColCount(0) { // This assert to be _NO_ASSUME since otherwise the compiler will assume that // the error checking branch here cannot be taken and optimize it away. const Scalar maxScalar = std::numeric_limits::max(); MATHICGB_ASSERT_NO_ASSUME(ring().charac() <= maxScalar); if (ring().charac() > maxScalar) mathic::reportInternalError("F4MatrixBuilder: too large characteristic."); } void F4MatrixBuilder::addSPolynomialToMatrix( const Poly& polyA, const Poly& polyB ) { MATHICGB_ASSERT(!polyA.isZero()); MATHICGB_ASSERT(polyA.isMonic()); MATHICGB_ASSERT(!polyB.isZero()); MATHICGB_ASSERT(polyB.isMonic()); RowTask task; task.addToTop = false; task.poly = &polyA; task.sPairPoly = &polyB; mTodo.push_back(task); } void F4MatrixBuilder::addPolynomialToMatrix(const Poly& poly) { if (poly.isZero()) return; RowTask task = {}; task.addToTop = false; task.poly = &poly; mTodo.push_back(task); } void F4MatrixBuilder::addPolynomialToMatrix (ConstMonoRef multiple, const Poly& poly) { if (poly.isZero()) return; auto desiredLead = monoid().alloc(); monoid().multiply(poly.leadMono(), multiple, desiredLead); RowTask task = {}; task.addToTop = false; task.poly = &poly; task.desiredLead = desiredLead.release(); MATHICGB_ASSERT(task.sPairPoly == 0); mTodo.push_back(task); } void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) { MATHICGB_ASSERT(&matrix.ring() == &ring()); MATHICGB_LOG_TIME(F4MatrixBuild) << "\n***** Constructing matrix *****\n"; if (mTodo.empty()) { matrix.clear(); return; } // todo: prefer sparse/old reducers among the inputs. // Process pending rows until we are done. Note that the methods // we are calling here can add more pending items. struct ThreadData { QuadMatrixBuilder builder; MonoRef tmp1; MonoRef tmp2; }; mgb::mtbb::enumerable_thread_specific threadData([&](){ mgb::mtbb::mutex::scoped_lock guard(mCreateColumnLock); ThreadData data = { QuadMatrixBuilder( ring(), mMap, mMonomialsLeft, mMonomialsRight, mBuilder.memoryQuantum() ), *monoid().alloc().release(), *monoid().alloc().release() }; return std::move(data); }); mgb::mtbb::parallel_do(mTodo.begin(), mTodo.end(), [&](const RowTask& task, TaskFeeder& feeder) { auto& data = threadData.local(); QuadMatrixBuilder& builder = data.builder; const Poly& poly = *task.poly; if (task.sPairPoly != 0) { MATHICGB_ASSERT(!task.addToTop); monoid().colons( poly.leadMono(), task.sPairPoly->leadMono(), data.tmp2, data.tmp1 ); appendRowBottom (poly, data.tmp1, *task.sPairPoly, data.tmp2, data.builder, feeder); return; } if (task.desiredLead == nullptr) monoid().setIdentity(data.tmp1); else monoid().divide(poly.leadMono(), *task.desiredLead, data.tmp1); if (task.addToTop) appendRowTop(data.tmp1, *task.poly, builder, feeder); else appendRowBottom (data.tmp1, false, poly.begin(), poly.end(), builder, feeder); }); MATHICGB_ASSERT(!threadData.empty()); // as mTodo empty causes early return // Free the monomials from all the tasks const auto todoEnd = mTodo.end(); for (auto& mono : mTodo) if (!mono.desiredLead.isNull()) monoid().freeRaw(*mono.desiredLead.castAwayConst()); mTodo.clear(); auto& builder = threadData.begin()->builder; for (auto& data : threadData) { if (&data.builder != &builder) builder.takeRowsFrom(data.builder.buildMatrixAndClear()); monoid().freeRaw(data.tmp1); monoid().freeRaw(data.tmp2); } matrix = builder.buildMatrixAndClear(); threadData.clear(); { ColReader reader(mMap); matrix.leftColumnMonomials.clear(); matrix.rightColumnMonomials.clear(); const auto end = reader.end(); for (auto it = reader.begin(); it != end; ++it) { const auto p = *it; auto copy = monoid().alloc(); monoid().copy(p.second, copy); auto& monos = p.first.left() ? matrix.leftColumnMonomials : matrix.rightColumnMonomials; const auto index = p.first.index(); if (monos.size() <= index) monos.resize(index + 1); MATHICGB_ASSERT(monos[index].isNull()); monos[index] = copy.release(); } } #ifdef MATHICGB_DEBUG for (size_t side = 0; side < 2; ++side) { auto& monos = side == 0 ? matrix.leftColumnMonomials : matrix.rightColumnMonomials; for (auto it = monos.begin(); it != monos.end(); ++it) { MATHICGB_ASSERT(!it->isNull()); } } #endif matrix.sortColumnsLeftRightParallel(); mMap.clearNonConcurrent(); } auto F4MatrixBuilder::createColumn( ConstMonoRef monoA, ConstMonoRef monoB, TaskFeeder& feeder ) -> std::pair { mgb::mtbb::mutex::scoped_lock lock(mCreateColumnLock); // see if the column exists now after we have synchronized { const auto found(ColReader(mMap).findProduct(monoA, monoB)); if (found.first != 0) return std::make_pair(*found.first, *found.second); } // The column really does not exist, so we need to create it monoid().multiply(monoA, monoB, mTmp); if (!monoid().hasAmpleCapacity(*mTmp)) mathic::reportError("Monomial exponent overflow in F4MatrixBuilder."); // look for a reducer of mTmp const size_t reducerIndex = mBasis.classicReducer(*mTmp); const bool insertLeft = (reducerIndex != static_cast(-1)); // Create the new left or right column auto& colCount = insertLeft ? mLeftColCount : mRightColCount; if (colCount == std::numeric_limits::max()) throw std::overflow_error("Too many columns in QuadMatrix"); const auto inserted = mMap.insert (std::make_pair(mTmp.ptr(), LeftRightColIndex(colCount, insertLeft))); ++colCount; MATHICGB_ASSERT(inserted.second); MATHICGB_ASSERT(inserted.first.first != 0); // schedule new task if we found a reducer if (insertLeft) { RowTask task = {}; task.addToTop = true; task.poly = &mBasis.poly(reducerIndex); task.desiredLead = inserted.first.second; feeder.add(task); } return std::make_pair(*inserted.first.first, *inserted.first.second); } void F4MatrixBuilder::appendRowBottom( ConstMonoRef multiple, const bool negate, const Poly::ConstTermIterator begin, const Poly::ConstTermIterator end, QuadMatrixBuilder& builder, TaskFeeder& feeder ) { // todo: eliminate the code-duplication between here and appendRowTop. MATHICGB_ASSERT(&builder != 0); auto it = begin; updateReader: // Use an on-stack const reader to make it as obvious as possible to the // optimizer's alias analysis that the pointer inside the reader never // changes inside the loop. const ColReader reader(mMap); for (; it != end; ++it) { const auto col = reader.findProduct(it.mono(), multiple); if (col.first == 0) { createColumn(it.mono(), multiple, feeder); goto updateReader; } const auto origScalar = it.coef(); MATHICGB_ASSERT(!ring().field().isZero(origScalar)); const auto maybeNegated = negate ? field().negativeNonZero(origScalar) : origScalar; MATHICGB_ASSERT(maybeNegated < std::numeric_limits::max()); builder.appendEntryBottom(*col.first, static_cast(maybeNegated)); } builder.rowDoneBottomLeftAndRight(); } void F4MatrixBuilder::appendRowTop( ConstMonoRef multiple, const Poly& poly, QuadMatrixBuilder& builder, TaskFeeder& feeder ) { MATHICGB_ASSERT(&poly != 0); MATHICGB_ASSERT(&builder != 0); auto it = poly.begin(); const auto end = poly.end(); if ((poly.termCount() % 2) == 1) { ColReader reader(mMap); const auto col = findOrCreateColumn (it.mono(), multiple, reader, feeder); MATHICGB_ASSERT(it.coef() < std::numeric_limits::max()); MATHICGB_ASSERT(!field().isZero(it.coef())); builder.appendEntryTop (col.first, static_cast(it.coef())); ++it; } updateReader: ColReader colMap(mMap); while (it != end) { MATHICGB_ASSERT(it.coef() < std::numeric_limits::max()); MATHICGB_ASSERT(!field().isZero(it.coef())); const auto scalar1 = static_cast(it.coef()); const auto mono1 = it.mono(); auto it2 = it; ++it2; MATHICGB_ASSERT(it2.coef() < std::numeric_limits::max()); MATHICGB_ASSERT(!field().isZero(it2.coef())); const auto scalar2 = static_cast(it2.coef()); const auto mono2 = it2.mono(); const auto colPair = colMap.findTwoProducts(mono1, mono2, multiple); if (colPair.first == 0 || colPair.second == 0) { createTwoColumns(mono1, mono2, multiple, feeder); goto updateReader; } builder.appendEntryTop(*colPair.first, scalar1); builder.appendEntryTop(*colPair.second, scalar2); it = ++it2; } builder.rowDoneTopLeftAndRight(); } void F4MatrixBuilder::appendRowBottom( const Poly& poly, ConstMonoRef multiply, const Poly& sPairPoly, ConstMonoRef sPairMultiply, QuadMatrixBuilder& builder, TaskFeeder& feeder ) { MATHICGB_ASSERT(!poly.isZero()); auto itA = poly.begin(); const auto endA = poly.end(); MATHICGB_ASSERT(!sPairPoly.isZero()); auto itB = sPairPoly.begin(); const auto endB = sPairPoly.end(); // skip leading terms since they cancel MATHICGB_ASSERT(itA.coef() == itB.coef()); ++itA; ++itB; const ColReader colMap(mMap); const auto mulA = multiply; const auto mulB = sPairMultiply; while (true) { // Watch out: we are depending on appendRowBottom to finish the row, so // if you decide not to call that function in case // (itA == itA && itB == endB) then you need to do that yourself. if (itB == endB) { appendRowBottom(mulA, false, itA, endA, builder, feeder); break; } if (itA == endA) { appendRowBottom(mulB, true, itB, endB, builder, feeder); break; } coefficient coeff = 0; LeftRightColIndex col; const auto colA = findOrCreateColumn (itA.mono(), mulA, colMap, feeder); const auto colB = findOrCreateColumn (itB.mono(), mulB, colMap, feeder); const auto cmp = monoid().compare(colA.second, colB.second); if (cmp != LT) { coeff = itA.coef(); col = colA.first; ++itA; } if (cmp != GT) { coeff = ring().coefficientSubtract(coeff, itB.coef()); col = colB.first; ++itB; } MATHICGB_ASSERT(coeff < std::numeric_limits::max()); if (!field().isZero(coeff)) builder.appendEntryBottom(col, static_cast(coeff)); } } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/F4MatrixBuilder.hpp000077500000000000000000000132711311555162500221630ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_F4_MATRIX_BUILDER_GUARD #define MATHICGB_F4_MATRIX_BUILDER_GUARD #include "QuadMatrixBuilder.hpp" #include "Poly.hpp" #include "PolyRing.hpp" #include "PolyBasis.hpp" #include "QuadMatrix.hpp" #include "mtbb.hpp" #include MATHICGB_NAMESPACE_BEGIN /// Class for constructing an F4 matrix. This class is reponsible for /// figuring out what matrix to build and then it uses QuadMatrixBuilder /// to create that matrix. /// /// @todo: this class does not offer exception guarantees. It's just not /// very workable without an RAII monomial handle, so add one of those /// before fixing this. class F4MatrixBuilder { private: typedef QuadMatrixBuilder::ColIndex ColIndex; typedef QuadMatrixBuilder::LeftRightColIndex LeftRightColIndex; typedef QuadMatrixBuilder::Scalar Scalar; typedef QuadMatrixBuilder::Map Map; typedef QuadMatrixBuilder::Monomials Monomials; public: typedef PolyRing::Field Field; typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; /// memoryQuantum is how much to increase the memory size by each time the /// current amount of memory is exhausted. A value of 0 indicates to start /// small and double the quantum at each exhaustion. F4MatrixBuilder(const PolyBasis& basis, size_t memoryQuantum = 0); /** Schedules a row representing the S-polynomial between polyA and polyB to be added to the matrix. No ownership is taken, but polyA and polyB must remain valid until the matrix is constructed. Currently, the two monomials must be monic, though this is just because they always happen to be monic so there was no reason to support the non-monic case. */ void addSPolynomialToMatrix(const Poly& polyA, const Poly& polyB); /** Schedules a row representing multiple*poly to be added to the matrix. No ownership is taken, but poly must remain valid until the matrix is constructed. multiple is copied so it need not remain valid. */ void addPolynomialToMatrix(ConstMonoRef multiple, const Poly& poly); /// as the overload with a multiple, just letting multiple be the /// identity. void addPolynomialToMatrix(const Poly& poly); /** Builds an F4 matrix to the specifications given. Also clears the information in this object. The right columns are ordered by decreasing monomial of each column according to the order from the basis. The left columns are ordered in some way so that the first entry in each top row (the pivot) has a lower index than any other entries in that row. The matrix contains a reducer/pivot for every monomial that can be reduced by the basis and that is present in the matrix. There is no guarantee that the bottom part of the matrix contains rows that exactly correspond to the polynomials that have been scheduled to be added to the matrix. It is only guaranteed that the whole matrix has the same row-space as though that had been the case. */ void buildMatrixAndClear(QuadMatrix& matrix); const PolyRing& ring() const {return mBuilder.ring();} const Monoid& monoid() const {return ring().monoid();} const Field& field() const {return ring().field();} private: typedef const MonomialMap::Reader ColReader; /// Represents the task of adding a row to the matrix. If sPairPoly is null /// then the row to add is multiply * poly. Otherwise, the row to add is /// multiply * poly - sPairMultiply * sPairPoly /// where sPairMultiply makes the lead terms cancel. struct RowTask { bool addToTop; // add the row to the bottom if false ConstMonoPtr desiredLead; // multiply monomial onto poly to get this lead const Poly* poly; const Poly* sPairPoly; ConstMonoPtr sPairMultiply; }; typedef mtbb::parallel_do_feeder TaskFeeder; /// Creates a column with monomial label x and schedules a new row to /// reduce that column if possible. Here x is monoA if monoB is /// null and otherwise x is the product of monoA and monoB. MATHICGB_NO_INLINE std::pair createColumn(ConstMonoRef monoA, ConstMonoRef monoB, TaskFeeder& feeder); void appendRowTop( ConstMonoRef multiple, const Poly& poly, QuadMatrixBuilder& builder, TaskFeeder& feeder ); void appendRowBottom( const Poly& poly, ConstMonoRef multiply, const Poly& sPairPoly, ConstMonoRef sPairMultiply, QuadMatrixBuilder& builder, TaskFeeder& feeder ); void appendRowBottom( ConstMonoRef multiple, bool negate, Poly::ConstTermIterator begin, Poly::ConstTermIterator end, QuadMatrixBuilder& builder, TaskFeeder& feeder ); MATHICGB_NO_INLINE std::pair findOrCreateColumn( ConstMonoRef monoA, ConstMonoRef monoB, TaskFeeder& feeder ); MATHICGB_INLINE std::pair findOrCreateColumn( ConstMonoRef monoA, ConstMonoRef monoB, const ColReader& colMap, TaskFeeder& feeder ); MATHICGB_NO_INLINE void createTwoColumns( ConstMonoRef monoA1, ConstMonoRef monoA2, ConstMonoRef monoB, TaskFeeder& feeder ); mgb::mtbb::mutex mCreateColumnLock; ColIndex mLeftColCount; ColIndex mRightColCount; Mono mTmp; const PolyBasis& mBasis; Monomials mMonomialsLeft; Monomials mMonomialsRight; QuadMatrixBuilder mBuilder; Map mMap; std::vector mTodo; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/F4MatrixBuilder2.cpp000077500000000000000000000512021311555162500222340ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "F4MatrixBuilder2.hpp" #include "LogDomain.hpp" #include "F4MatrixProjection.hpp" MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixBuild2, "Displays statistics about F4 matrix construction." ); MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixSizes, "Displays row and column count for each F4 matrix construction." ); MATHICGB_NAMESPACE_BEGIN class F4MatrixBuilder2::Builder { public: typedef PolyRing::Field Field; typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef SparseMatrix::ColIndex ColIndex; typedef SparseMatrix::Scalar Scalar; typedef MonomialMap Map; typedef SparseMatrix::RowIndex RowIndex; /// Initializes the set of add-this-row tasks. void initializeRowsToReduce(std::vector& tasks) { // If aF-bG is an S-pair that is added as a bottom row in the matrix, and // we do not already have a reducer for the common leading term of aF and // bG, then we can instead set bG as a top/reducer/pivot row and put aF // as a bottom row. This way, we do not need to add a reducer for that // column if that monomial turns out to be used. We can also use the // faster code path for adding a single multiple like aF to the matrix // instead of the more complicated path that adds the difference between // two multiples aF-bG. // // If bG is already the top/reducer/pivot row for its leading monomial, // then we can simply replace a bottom row aF-bG with aF directly, since // the first computation that will happen will be to calculate aF-bG. // This way we get to use the much faster code in the matrix reducer for // making that reduction/Gaussian-elimination step. More importantly, we // have 1 row less to construct. // // The above two cases turn rows specified like aF-bG into rows specified // more simply as just aF. Note that we can interchange aF and bG in these // arguments with no problems. // // These two cases will apply to all // S-pairs with a given leading monomial if and only if there is a single // bG that appears in all of those S-pairs. The absolute best case is // if that single common bG is at the same time the most preferable // (sparsest or oldest) reducer for that monomial. It is not trivial to // realize this (in fact I should write a paper it), but the particular // way that S-pair elimination works in MathicGB ensures that this best // case is always the case. So the code below will get rid of all the // S-pairs aF-bG and replace them with single bottom rows aF. // However, if the S-pair elimination code is ever changed, that may // no longer be the case, so this code is still supposed to work even // if some S-pairs are not gotten rid of. Still, there is an assert // to flag it if the S-pair elimination is accidentally broken so that it // no longer gives this guarantee. // Bring S-pairs with the same leading monomial together by ordering // them according in increasing order of monomial. Put the non-S-pairs // together at the front. auto cmp = [&](const RowTask& a, const RowTask& b) { if (a.sPairPoly == nullptr) return b.sPairPoly != nullptr; else return monoid().lessThan(*a.desiredLead, *b.desiredLead); }; mgb::mtbb::parallel_sort(tasks.begin(), tasks.end(), cmp); const auto taskCount = tasks.size(); for (size_t i = 0; i < taskCount;) { if (tasks[i].sPairPoly == 0) { ++i; continue; } MATHICGB_ASSERT(tasks[i].desiredLead != nullptr); MATHICGB_ASSERT(ColReader(mMap).find(*tasks[i].desiredLead).first == 0); // Create column for the lead term that cancels in the S-pair if (mIsColumnToLeft.size() >= std::numeric_limits::max()) throw std::overflow_error("Too many columns in matrix."); const auto newIndex = static_cast(mIsColumnToLeft.size()); const auto inserted = mMap.insert(std::make_pair(tasks[i].desiredLead, newIndex)); mIsColumnToLeft.push_back(true); const auto& mono = inserted.first.second; // Schedule the two parts of the S-pair as separate rows. This adds a row // while creating the column in the hash table without adding a reducer // removes a row, effectively making this operation equivalent to taking // half of the S-pair and using it as a reducer. auto desiredLead = monoid().alloc(); monoid().copy(*mono, *desiredLead); RowTask newTask = {desiredLead.release(), tasks[i].sPairPoly, nullptr}; // Now we can strip off any part of an S-pair with the same cancelling lead // term that equals a or b since those rows are in the matrix. const auto* const a = tasks[i].poly; const auto* const b = tasks[i].sPairPoly; tasks[i].sPairPoly = 0; tasks.push_back(newTask); for (++i; i < taskCount; ++i) { auto& task = tasks[i]; if (tasks[i].sPairPoly == 0) continue; MATHICGB_ASSERT(tasks[i].desiredLead != nullptr); if (!monoid().equal(*tasks[i].desiredLead, *mono)) break; if (tasks[i].poly == a || tasks[i].poly == b) { tasks[i].poly = tasks[i].sPairPoly; tasks[i].sPairPoly = 0; } else if (tasks[i].sPairPoly == a || tasks[i].sPairPoly == b) { tasks[i].sPairPoly = 0; } else MATHICGB_ASSERT(false); } } } void buildMatrixAndClear(std::vector& tasks, QuadMatrix& quadMatrix) { MATHICGB_ASSERT(&quadMatrix.ring() == &ring()); MATHICGB_LOG_TIME(F4MatrixBuild2) << "\n***** Constructing matrix *****\n"; if (tasks.empty()) { quadMatrix.clear(); return; } initializeRowsToReduce(tasks); // The MonoRef's cannot be Mono's since enumerable_thread_specific // apparently requires the stored data type to be copyable and // Mono is not copyable. struct ThreadData { MonoRef tmp1; MonoRef tmp2; F4ProtoMatrix block; }; mgb::mtbb::enumerable_thread_specific threadData([&](){ // We need to grab a lock since monoid isn't internally synchronized. mgb::mtbb::mutex::scoped_lock guard(mCreateColumnLock); ThreadData data = { *monoid().alloc().release(), *monoid().alloc().release() }; return data; }); // Construct the matrix as pre-blocks mgb::mtbb::parallel_do(tasks.begin(), tasks.end(), [&](const RowTask& task, TaskFeeder& feeder) { auto& data = threadData.local(); const auto& poly = *task.poly; // It is perfectly permissible for task.sPairPoly to be non-null. The // assert is there because of an interaction between S-pair // elimination/choice and the use of halves of S-pairs as reducers. The // current effect of these is that *all* S-pairs have a component split // off so that sPairPoly is always null (this is non-trivial to // realize). So if this assert goes off, you've messed that interaction // up somehow or you are using this class in some new way. So you can // remove the assert if necessary. MATHICGB_ASSERT(task.sPairPoly == 0); if (task.sPairPoly != 0) { monoid().colons( poly.leadMono(), task.sPairPoly->leadMono(), data.tmp2, data.tmp1 ); appendRowSPair (poly, data.tmp1, *task.sPairPoly, data.tmp2, data.block, feeder); return; } if (task.desiredLead == nullptr) monoid().setIdentity(data.tmp1); else monoid().divide(poly.leadMono(), *task.desiredLead, data.tmp1); appendRow(data.tmp1, *task.poly, data.block, feeder); }); MATHICGB_ASSERT(!threadData.empty()); // as tasks empty causes early return // Free the monomials from all the tasks for (const auto& task : tasks) if (task.desiredLead != nullptr) monoid().freeRaw(*task.desiredLead.castAwayConst()); tasks.clear(); // Move the proto-matrices across all threads into the projection. F4MatrixProjection projection (ring(), static_cast(mMap.entryCount())); const auto end = threadData.end(); for (auto& data : threadData) { monoid().freeRaw(data.tmp1); monoid().freeRaw(data.tmp2); projection.addProtoMatrix(std::move(data.block)); } // Sort columns by monomial and tell the projection of the resulting order MonomialMap::Reader reader(mMap); typedef std::pair IndexMono; auto toPtr = [](std::pair p) { return std::make_pair(p.first, &p.second); }; std::vector columns; std::transform (reader.begin(), reader.end(), std::back_inserter(columns), toPtr); const auto cmp = [&](const IndexMono& a, const IndexMono b) { return monoid().lessThan(*b.second, *a.second); }; mgb::mtbb::parallel_sort(columns.begin(), columns.end(), cmp); const auto colEnd = columns.end(); for (auto it = columns.begin(); it != colEnd; ++it) { const auto p = *it; projection.addColumn(p.first, *p.second, mIsColumnToLeft[p.first]); } quadMatrix = projection.makeAndClear(mMemoryQuantum); MATHICGB_LOG(F4MatrixSizes) << "F4[" << mathic::ColumnPrinter::commafy(quadMatrix.rowCount()) << " by " << mathic::ColumnPrinter::commafy( quadMatrix.computeLeftColCount() + quadMatrix.computeRightColCount()) << "]" << std::endl; #ifdef MATHICGB_DEBUG for (size_t side = 0; side < 2; ++side) { auto& monos = side == 0 ? quadMatrix.leftColumnMonomials : quadMatrix.rightColumnMonomials; for (auto it = monos.begin(); it != monos.end(); ++it) { MATHICGB_ASSERT(!it->isNull()); } } for (RowIndex row = 0; row < quadMatrix.topLeft.rowCount(); ++row) { MATHICGB_ASSERT(quadMatrix.topLeft.entryCountInRow(row) > 0); MATHICGB_ASSERT(quadMatrix.topLeft.leadCol(row) == row); } MATHICGB_ASSERT(quadMatrix.debugAssertValid()); #endif } const PolyRing& ring() const {return mBasis.ring();} const Monoid& monoid() const {return ring().monoid();} const Field& field() const {return ring().field();} Builder(const PolyBasis& basis, const size_t memoryQuantum): mMemoryQuantum(memoryQuantum), mTmp(basis.ring().monoid().alloc()), mBasis(basis), mMap(basis.ring()) { // This assert has to be _NO_ASSUME since otherwise the compiler will // assume that the error checking branch here cannot be taken and optimize // it away. const Scalar maxScalar = std::numeric_limits::max(); MATHICGB_ASSERT_NO_ASSUME(ring().charac() <= maxScalar); if (ring().charac() > maxScalar) mathic::reportInternalError("F4MatrixBuilder2: too large characteristic."); } typedef const Map::Reader ColReader; typedef std::vector Monomials; typedef mgb::mtbb::parallel_do_feeder TaskFeeder; /// Creates a column with monomial label monoA * monoB and schedules a new /// row to reduce that column if possible. If such a column already /// exists, then a new column is not inserted. In either case, returns /// the column index and column monomial corresponding to monoA * monoB. /// /// createColumn can be used simply to search for an existing column, but /// since createColumn incurs locking overhead, this is not a good idea. /// Note that createColumn has to work correctly for pre-existing columns /// because the only way to be *certain* that no other thread has inserted /// the column of interest is to grab a lock, and the lock being grabbed /// is being grabbed inside createColumn. MATHICGB_NO_INLINE std::pair createColumn( ConstMonoRef monoA, ConstMonoRef monoB, TaskFeeder& feeder ) { mgb::mtbb::mutex::scoped_lock lock(mCreateColumnLock); // see if the column exists now after we have synchronized { const auto found(ColReader(mMap).findProduct(monoA, monoB)); if (found.first != 0) return std::make_pair(*found.first, *found.second); } // The column really does not exist, so we need to create it monoid().multiply(monoA, monoB, mTmp); if (!monoid().hasAmpleCapacity(*mTmp)) mathic::reportError("Monomial exponent overflow in F4MatrixBuilder2."); // look for a reducer of mTmp const size_t reducerIndex = mBasis.classicReducer(*mTmp); const bool insertLeft = (reducerIndex != static_cast(-1)); // Create the new left or right column if (mIsColumnToLeft.size() >= std::numeric_limits::max()) throw std::overflow_error("Too many columns in QuadMatrix"); const auto newIndex = static_cast(mIsColumnToLeft.size()); const auto inserted = mMap.insert(std::make_pair(mTmp.ptr(), newIndex)); mIsColumnToLeft.push_back(insertLeft); // schedule new task if we found a reducer if (insertLeft) { RowTask task = {}; task.poly = &mBasis.poly(reducerIndex); task.desiredLead = inserted.first.second; feeder.add(task); } return std::make_pair(*inserted.first.first, *inserted.first.second); } /// Append multiple * poly to block, creating new columns as necessary. void appendRow( ConstMonoRef multiple, const Poly& poly, F4ProtoMatrix& block, TaskFeeder& feeder ) { const auto begin = poly.begin(); const auto end = poly.end(); const auto count = poly.termCount(); MATHICGB_ASSERT(count < std::numeric_limits::max()); auto indices = block.makeRowWithTheseScalars(poly); auto it = begin; if ((count % 2) == 1) { ColReader reader(mMap); const auto col = findOrCreateColumn (it.mono(), multiple, reader, feeder); MATHICGB_ASSERT(it.coef() < std::numeric_limits::max()); MATHICGB_ASSERT(!field().isZero(it.coef())); *indices = col.first; ++indices; ++it; } updateReader: ColReader colMap(mMap); while (it != end) { MATHICGB_ASSERT(it.coef() < std::numeric_limits::max()); MATHICGB_ASSERT(!field().isZero(it.coef())); const auto scalar1 = static_cast(it.coef()); const auto mono1 = it.mono(); auto it2 = it; ++it2; MATHICGB_ASSERT(it2.coef() < std::numeric_limits::max()); MATHICGB_ASSERT(!field().isZero(it2.coef())); const auto scalar2 = static_cast(it2.coef()); const auto mono2 = it2.mono(); const auto colPair = colMap.findTwoProducts(mono1, mono2, multiple); if (colPair.first == 0 || colPair.second == 0) { createColumn(mono1, multiple, feeder); createColumn(mono2, multiple, feeder); goto updateReader; } *indices = *colPair.first; ++indices; *indices = *colPair.second; ++indices; it = ++it2; } } /// Append poly*multiply - sPairPoly*sPairMultiply to block, creating new /// columns as necessary. void appendRowSPair( const Poly& poly, ConstMonoRef multiply, const Poly& sPairPoly, ConstMonoRef sPairMultiply, F4ProtoMatrix& block, TaskFeeder& feeder ) { MATHICGB_ASSERT(!poly.isZero()); auto itA = poly.begin(); const auto endA = poly.end(); MATHICGB_ASSERT(!sPairPoly.isZero()); auto itB = sPairPoly.begin(); const auto endB = sPairPoly.end(); // skip leading terms since they cancel MATHICGB_ASSERT(itA.coef() == itB.coef()); ++itA; ++itB; // @todo: handle overflow of termCount addition here MATHICGB_ASSERT(poly.termCount() + sPairPoly.termCount() - 2 <= std::numeric_limits::max()); const auto maxCols = static_cast(poly.termCount() + sPairPoly.termCount() - 2); auto row = block.makeRow(maxCols); const auto indicesBegin = row.first; const ColReader colMap(mMap); auto mulA = multiply; auto mulB = sPairMultiply; while (itB != endB && itA != endA) { const auto colA = findOrCreateColumn (itA.mono(), mulA, colMap, feeder); const auto colB = findOrCreateColumn (itB.mono(), mulB, colMap, feeder); const auto cmp = monoid().compare(colA.second, colB.second); coefficient coeff = 0; ColIndex col; if (cmp != LT) { coeff = itA.coef(); col = colA.first; ++itA; } if (cmp != GT) { coeff = ring().coefficientSubtract(coeff, itB.coef()); col = colB.first; ++itB; } MATHICGB_ASSERT(coeff < std::numeric_limits::max()); if (coeff != 0) { *row.first++ = col; *row.second++ = static_cast(coeff); } } for (; itA != endA; ++itA) { const auto colA = findOrCreateColumn (itA.mono(), mulA, colMap, feeder); *row.first++ = colA.first; *row.second++ = static_cast(itA.coef()); } for (; itB != endB; ++itB) { const auto colB = findOrCreateColumn (itB.mono(), mulB, colMap, feeder); const auto negative = ring().coefficientNegate(itB.coef()); *row.first = colB.first; ++row.first; *row.second = static_cast(negative); ++row.second; } const auto toRemove = maxCols - static_cast(row.first - indicesBegin); block.removeLastEntries(block.rowCount() - 1, toRemove); } /// As createColumn, except with much better performance in the common /// case that the column for monoA * monoB already exists. In particular, /// no lock is grabbed in that case. MATHICGB_NO_INLINE std::pair findOrCreateColumn( ConstMonoRef monoA, ConstMonoRef monoB, TaskFeeder& feeder ) { const auto col = ColReader(mMap).findProduct(monoA, monoB); if (col.first != 0) return std::make_pair(*col.first, *col.second); return createColumn(monoA, monoB, feeder); } /// As the overload that does not take a ColReader parameter, except with /// better performance in the common case that the column already exists /// and colMap is up-to-date. MATHICGB_INLINE std::pair findOrCreateColumn( ConstMonoRef monoA, ConstMonoRef monoB, const ColReader& colMap, TaskFeeder& feeder ) { const auto col = colMap.findProduct(monoA, monoB); if (col.first == 0) { // The reader may be out of date, so try again with a fresh reader. return findOrCreateColumn(monoA, monoB, feeder); } return std::make_pair(*col.first, *col.second); } /// The split into left and right columns is not done until the whole matrix /// has been constructed. This vector keeps track of which side each column /// should go to once we do the split. char is used in place of bool because /// the specialized bool would just be slower for this use case. See /// http://isocpp.org/blog/2012/11/on-vectorbool . std::vector mIsColumnToLeft; /// How much memory to allocate every time more memory is needed. const size_t mMemoryQuantum; /// If you want to modify the columns, you need to grab this lock first. mgb::mtbb::mutex mCreateColumnLock; /// A monomial for temporary scratch calculations. Protected by /// mCreateColumnLock. Mono mTmp; /// Mapping from monomials to column indices. Map mMap; /// The basis that supplies reducers. const PolyBasis& mBasis; }; F4MatrixBuilder2::F4MatrixBuilder2( const PolyBasis& basis, const size_t memoryQuantum ): mBasis(basis), mMemoryQuantum(memoryQuantum) {} void F4MatrixBuilder2::addSPolynomialToMatrix( const Poly& polyA, const Poly& polyB ) { MATHICGB_ASSERT(!polyA.isZero()); MATHICGB_ASSERT(polyA.isMonic()); MATHICGB_ASSERT(!polyB.isZero()); MATHICGB_ASSERT(polyB.isMonic()); auto desiredLead = monoid().alloc(); monoid().lcm(polyA.leadMono(), polyB.leadMono(), *desiredLead); RowTask task = {desiredLead.release(), &polyA, &polyB}; mTodo.push_back(task); } void F4MatrixBuilder2::addPolynomialToMatrix(const Poly& poly) { if (poly.isZero()) return; RowTask task = {}; task.poly = &poly; mTodo.push_back(task); } void F4MatrixBuilder2::addPolynomialToMatrix( ConstMonoRef multiple, const Poly& poly ) { if (poly.isZero()) return; auto desiredLead = monoid().alloc(); monoid().multiply(poly.leadMono(), multiple, desiredLead); RowTask task = {desiredLead.release(), &poly, nullptr}; mTodo.push_back(task); } void F4MatrixBuilder2::buildMatrixAndClear(QuadMatrix& quadMatrix) { Builder builder(mBasis, mMemoryQuantum); builder.buildMatrixAndClear(mTodo, quadMatrix); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/F4MatrixBuilder2.hpp000077500000000000000000000077431311555162500222540ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_F4_MATRIX_BUILDER_2_GUARD #define MATHICGB_F4_MATRIX_BUILDER_2_GUARD #include "SparseMatrix.hpp" #include "Poly.hpp" #include "PolyRing.hpp" #include "PolyBasis.hpp" #include "QuadMatrix.hpp" #include "MonomialMap.hpp" #include "F4ProtoMatrix.hpp" #include "mtbb.hpp" #include MATHICGB_NAMESPACE_BEGIN /// Class for constructing an F4 matrix. /// /// @todo: this class does not offer exception guarantees. It's just not /// very workable without an RAII monomial handle or a scope exit /// functionality, so add one of those before fixing this. class F4MatrixBuilder2 { public: typedef PolyRing::Field Field; typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; /// memoryQuantum is how much to increase the memory size by each time the /// current amount of memory is exhausted. A value of 0 indicates to start /// small and double the quantum at each exhaustion. F4MatrixBuilder2(const PolyBasis& basis, size_t memoryQuantum = 0); /// Schedules a row representing the S-polynomial between polyA and /// polyB to be added to the matrix. No ownership is taken, but polyA /// and polyB must remain valid until the matrix is constructed. /// /// Currently, the two monomials must be monic, though this is just /// because they happen always to be monic so there was no reason to /// support the non-monic case. void addSPolynomialToMatrix(const Poly& polyA, const Poly& polyB); /// Schedules a row representing multiple*poly to be added to the /// matrix. No ownership is taken, but poly must remain valid until /// the matrix is constructed. multiple is copied, so it need not /// remain valid. void addPolynomialToMatrix(ConstMonoRef multiple, const Poly& poly); /// As the overload with a multiple, where the multiple is 1. void addPolynomialToMatrix(const Poly& poly); /// Builds an F4 matrix to the specifications given. Also clears the /// information in this object. /// /// The right columns are in order of strictly decreasing monomial. /// The left columns are ordered in some way so that the leading non-zero /// entry in each top row has the maximal column monomial out of all /// non-zero entries in that row. /// /// The monomials that can be reduced by some element of the basis go on /// the left while the remaining monomials go on the right. The upper left /// matrix is upper triangular, thus having a reducer/pivot row for every /// column. /// /// There is no guarantee that the bottom part of the matrix contains rows /// that exactly correspond to the polynomials that have been scheduled to /// be added to the matrix. It is only guaranteed that the whole matrix has /// the same row-space as though that had been the case. void buildMatrixAndClear(QuadMatrix& matrix); const PolyRing& ring() const {return mBasis.ring();} const Monoid& monoid() const {return ring().monoid();} const Field& field() const {return ring().field();} private: /// Represents the task of adding a row to the matrix. If sPairPoly is null /// then the row to add is multiply * poly. Otherwise, the row to add is /// multiply * poly - sPairMultiply * sPairPoly /// where multiply and sPairMultiply are such that the leading terms become /// desiredLead. struct RowTask { ConstMonoPtr desiredLead; // multiply a monomial onto poly to get this lead const Poly* poly; const Poly* sPairPoly; }; class Builder; /// How much memory to allocate every time more memory is needed. const size_t mMemoryQuantum; /// The basis that supplies reducers. const PolyBasis& mBasis; /// Stores the rows that have been scheduled to be added. std::vector mTodo; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/F4MatrixProjection.cpp000077500000000000000000000256051311555162500227100ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "F4MatrixProjection.hpp" #include "ScopeExit.hpp" MATHICGB_NAMESPACE_BEGIN F4MatrixProjection::F4MatrixProjection( const PolyRing& ring, ColIndex colCount ): mRing(ring), mColProjectTo(colCount) {} void F4MatrixProjection::addColumn( const ColIndex projectFrom, ConstMonoRef mono, const bool isLeft ) { MATHICGB_ASSERT(projectFrom < mColProjectTo.size()); MATHICGB_ASSERT (mLeftMonomials.size() + mRightMonomials.size() < mColProjectTo.size()); auto monoCopy = mRing.monoid().alloc(); mRing.monoid().copy(mono, *monoCopy); auto& projected = mColProjectTo[projectFrom]; if (isLeft) { projected.isLeft = true; projected.index = static_cast(mLeftMonomials.size()); mLeftMonomials.push_back(monoCopy.ptr()); } else { projected.isLeft = false; projected.index = static_cast(mRightMonomials.size()); mRightMonomials.push_back(monoCopy.ptr()); } monoCopy.release(); } struct RowData : F4ProtoMatrix::Row { RowData(): F4ProtoMatrix::Row() {} RowData(const F4ProtoMatrix::Row& row): F4ProtoMatrix::Row(row) {} }; typedef std::pair RowProjectFrom; template class F4MatrixProjection::TopBottom { public: typedef std::pair RowMultiple; typedef std::vector RowVector; TopBottom(const size_t leftColCount, const PolyRing& ring): mModulus(static_cast(ring.charac())), mTopRows(leftColCount) { MATHICGB_ASSERT(ring.charac() <= std::numeric_limits::max()); MATHICGB_ASSERT(leftColCount <= std::numeric_limits::max()); } void addRow(const Row& row, ColIndex leadIndex, Scalar leadScalar) { if (row.entryCount == 0) return; // Skip zero rows. if (leadIndex == std::numeric_limits::max()) { // this row has no left entries, so it cannot be a top row. mBottomRows.push_back(RowMultiple(row, 1)); return; } const auto currentTop = mTopRows[leadIndex].first; if ( currentTop.entryCount != 0 && // already have a reducer and... currentTop.entryCount < row.entryCount // ...it is sparser/better ) { mBottomRows.push_back(RowMultiple(row, 1)); } else { if (currentTop.entryCount != 0) mBottomRows.push_back(std::make_pair(currentTop, 1)); MATHICGB_ASSERT(leadScalar != 0); const auto inverse = leadScalar == 1 ? // 1 is a common case 1 : modularInverse(leadScalar, mModulus); mTopRows[leadIndex] = RowMultiple(row, inverse); } } bool debugAssertValid() { #ifdef MATHICGB_DEBUG auto check = [](RowMultiple r) { MATHICGB_ASSERT(r.first.entryCount > 0); MATHICGB_ASSERT(r.second != 0); }; std::for_each(mTopRows.begin(), mTopRows.end(), check); std::for_each(mBottomRows.begin(), mBottomRows.end(), check); #endif return true; } Scalar modulus() const {return mModulus;} const RowVector& top() const {return mTopRows;} const RowVector& bottom() const {return mBottomRows;} RowVector moveTop() {return mTopRows;} RowVector moveBottom() {return mBottomRows;} private: const Scalar mModulus; RowVector mTopRows; RowVector mBottomRows; }; class F4MatrixProjection::LeftRight { public: typedef F4ProtoMatrix::ExternalScalar ExternalScalar; typedef F4ProtoMatrix::Row Row; LeftRight( const std::vector& colProjectTo, const PolyRing& ring, const size_t quantum ): mColProjectTo(colProjectTo), mModulus(static_cast(ring.charac())), mLeft(quantum), mRight(quantum) { MATHICGB_ASSERT(ring.charac() < std::numeric_limits::max()); mLeft.clear(); mRight.clear(); } template void appendRowsPermuted(const std::vector& rows) { const auto end = rows.end(); for (auto it = rows.begin(); it != end; ++it) appendRow(it->first, it->second); } void appendRows(const std::vector& preBlocks) { const auto end = preBlocks.end(); for (auto it = preBlocks.begin(); it != end; ++it) { auto& block = **it; const auto rowCount = block.rowCount(); for (SparseMatrix::RowIndex r = 0; r < rowCount; ++r) { const auto row = block.row(r); if (row.entryCount > 0) appendRow(row); } } } void appendRow(const Row& row) { MATHICGB_ASSERT(row.entryCount > 0); // could be OK, but unexpected const auto indicesEnd = row.indices + row.entryCount; if (row.scalars == nullptr) appendRow(row.indices, indicesEnd, row.externalScalars); else appendRow(row.indices, indicesEnd, row.scalars); } void appendRow(const Row& row, Scalar multiplyBy) { MATHICGB_ASSERT(multiplyBy != 0); appendRow(row); if (multiplyBy != 1) { const auto rowIndex = mLeft.rowCount() - 1; mLeft.multiplyRow(rowIndex, multiplyBy, mModulus); mRight.multiplyRow(rowIndex, multiplyBy, mModulus); } } template void appendRow( IndexIter indices, const IndexIter indicesEnd, ScalarIter scalars ) { for (; indices != indicesEnd; ++indices, ++scalars) appendEntry(*indices, *scalars); rowDone(); } void appendEntry(const ColIndex projectMe, const Scalar scalar) { MATHICGB_ASSERT(scalar < mModulus); MATHICGB_ASSERT(mLeft.rowCount() == mRight.rowCount()); MATHICGB_ASSERT(projectMe < mColProjectTo.size()); const auto projected = mColProjectTo[projectMe]; if (projected.isLeft) mLeft.appendEntry(projected.index, scalar); else mRight.appendEntry(projected.index, scalar); } void appendEntry(const ColIndex projectMe, const ExternalScalar scalar) { MATHICGB_ASSERT(scalar <= std::numeric_limits::max()); appendEntry(projectMe, static_cast(scalar)); } void rowDone() { MATHICGB_ASSERT(mLeft.rowCount() == mRight.rowCount()); mLeft.rowDone(); mRight.rowDone(); }; const SparseMatrix& left() const {return mLeft;} const SparseMatrix& right() const {return mRight;} SparseMatrix moveLeft() {return std::move(mLeft);} SparseMatrix moveRight() {return std::move(mRight);} private: const std::vector& mColProjectTo; const Scalar mModulus; SparseMatrix mLeft; SparseMatrix mRight; }; QuadMatrix F4MatrixProjection::makeAndClear(const size_t quantum) { if (true) return makeAndClearOneStep(quantum); else return makeAndClearTwoStep(quantum); } QuadMatrix F4MatrixProjection::makeAndClearOneStep(const size_t quantum) { // Construct top/bottom row permutation TopBottom tb(mLeftMonomials.size(), ring()); const auto end = mMatrices.end(); for (auto it = mMatrices.begin(); it != end; ++it) { const auto& matrix = **it; const auto rowCount = matrix.rowCount(); for (RowIndex r = 0; r < rowCount; ++r) { const auto& row = matrix.row(r); // const ref keeps temporary alive if (row.entryCount == 0) continue; // ignore zero rows // *** Look for leading left entry ColIndex lead = 0; for (; lead < row.entryCount; ++lead) { MATHICGB_ASSERT(row.indices[lead] < mColProjectTo.size()); auto const projected = mColProjectTo[row.indices[lead]]; if (projected.isLeft) { const auto leadScalar = row.scalars != nullptr ? row.scalars[lead] : static_cast(row.externalScalars[lead]); tb.addRow(row, projected.index, leadScalar); goto done; } } // Did not find any left entry. tb.addRow(row, std::numeric_limits::max(), 0); done:; } } MATHICGB_ASSERT(tb.debugAssertValid()); // Split left/right and top/bottom simultaneously LeftRight top(mColProjectTo, ring(), quantum); top.appendRowsPermuted(tb.moveTop()); LeftRight bottom(mColProjectTo, ring(), 0); bottom.appendRowsPermuted(tb.moveBottom()); // Move the data into place QuadMatrix qm(ring()); qm.leftColumnMonomials = std::move(mLeftMonomials); qm.rightColumnMonomials = std::move(mRightMonomials); qm.topLeft = top.moveLeft(); qm.topRight = top.moveRight(); qm.bottomLeft = bottom.moveLeft(); qm.bottomRight = bottom.moveRight(); return std::move(qm); } namespace { // Helper function for F4MatrixProjection::makeAndClearTwoStep template std::pair projectRows( const TopBottom& tb, size_t quantum, SparseMatrix&& in ) { const auto modulus = tb.modulus(); SparseMatrix top(quantum); const auto topRows = tb.top(); const auto rowCountTop = static_cast(topRows.size()); for (SparseMatrix::RowIndex toRow = 0; toRow < rowCountTop; ++toRow) { top.appendRow(in, topRows[toRow].first.index); if (topRows[toRow].second != 1) top.multiplyRow(toRow, topRows[toRow].second, modulus); } SparseMatrix bottom(quantum); const auto bottomRows = tb.bottom(); const auto rowCountBottom = static_cast(bottomRows.size()); for (SparseMatrix::RowIndex toRow = 0; toRow < rowCountBottom; ++toRow) { bottom.appendRow(in, bottomRows[toRow].first.index); if (bottomRows[toRow].second != 1) bottom.multiplyRow(toRow, bottomRows[toRow].second, modulus); } in.clear(); return std::make_pair(std::move(top), std::move(bottom)); } } QuadMatrix F4MatrixProjection::makeAndClearTwoStep(const size_t quantum) { // Split whole matrix into left/right LeftRight lr(mColProjectTo, ring(), quantum); lr.appendRows(mMatrices); // Construct top/bottom matrix permutation struct Row { RowIndex index; ColIndex entryCount; }; TopBottom tb(mLeftMonomials.size(), ring()); const auto rowCount = lr.left().rowCount(); for (SparseMatrix::RowIndex row = 0; row < rowCount; ++row) { const auto leftEntryCount = lr.left().entryCountInRow(row); const auto entryCount = leftEntryCount + lr.right().entryCountInRow(row); MATHICGB_ASSERT(entryCount >= leftEntryCount); // no overflow if (entryCount == 0) continue; // ignore zero rows const Row r = {row, entryCount}; if (leftEntryCount == 0) tb.addRow(r, std::numeric_limits::max(), 0); else { const auto entry = lr.left().rowBegin(row); tb.addRow(r, entry.index(), entry.scalar()); } } MATHICGB_ASSERT(tb.debugAssertValid()); QuadMatrix qm(ring()); auto left = projectRows(tb, quantum, lr.moveLeft()); auto right = projectRows(tb, quantum, lr.moveRight()); qm.topLeft = std::move(left.first); qm.bottomLeft = std::move(left.second); qm.topRight = std::move(right.first); qm.bottomRight = std::move(right.second); qm.leftColumnMonomials = std::move(mLeftMonomials); qm.rightColumnMonomials = std::move(mRightMonomials); return std::move(qm); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/F4MatrixProjection.hpp000077500000000000000000000034031311555162500227050ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_F4_MATRIX_PROJECTION_GUARD #define MATHICGB_F4_MATRIX_PROJECTION_GUARD #include "QuadMatrix.hpp" #include "SparseMatrix.hpp" #include "F4ProtoMatrix.hpp" #include "MonomialMap.hpp" #include "ScopeExit.hpp" #include MATHICGB_NAMESPACE_BEGIN class F4MatrixProjection { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef SparseMatrix::RowIndex RowIndex; typedef SparseMatrix::ColIndex ColIndex; typedef SparseMatrix::Scalar Scalar; F4MatrixProjection(const PolyRing& ring, ColIndex colCount); void addProtoMatrix(F4ProtoMatrix&& matrix) {mMatrices.push_back(&matrix);} // No reference to mono is retained. void addColumn(ColIndex index, ConstMonoRef mono, const bool isLeft); QuadMatrix makeAndClear(const size_t quantum); const PolyRing& ring() const {return mRing;} private: QuadMatrix makeAndClearOneStep(const size_t quantum); QuadMatrix makeAndClearTwoStep(const size_t quantum); // Utility class for building a left/right projection. class LeftRight; // Utility class for building a top/bottom projection. template class TopBottom; // This is for projection of columns struct ColProjectTo { ColIndex index; bool isLeft; }; std::vector mColProjectTo; std::vector mMatrices; std::vector mLeftMonomials; std::vector mRightMonomials; const PolyRing& mRing; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/F4MatrixReducer.cpp000077500000000000000000000654061311555162500221700ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "F4MatrixReducer.hpp" #include "QuadMatrix.hpp" #include "SparseMatrix.hpp" #include "PolyRing.hpp" #include "LogDomain.hpp" #include "mtbb.hpp" #include #include #include #include #include #include #include MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixReduce, "Displays statistics about matrices that are row reduced." ); MATHICGB_DEFINE_LOG_DOMAIN( F4MatReduceTop, "Displays time to reduce each F4 matrix to the bottom right submatrix." ); MATHICGB_DEFINE_LOG_DOMAIN( F4RedBottomRight, "Displays time to reduce the bottom right submatrix of each F4 matrix." ); MATHICGB_NAMESPACE_BEGIN namespace { class DenseRow { public: typedef uint16 Scalar; typedef uint32 ScalarProduct; typedef uint64 ScalarProductSum; static ScalarProduct product(const Scalar a, const Scalar b) { return static_cast(a) * b; } static void multiplyAdd( const Scalar a, const Scalar b, ScalarProductSum& x ) { x += product(a, b); } static void add(const Scalar a, ScalarProductSum& sum) { sum += a; } Scalar modulusOf(ScalarProductSum x, Scalar modulus) { return static_cast(x % modulus); } DenseRow() {} DenseRow(size_t colCount): mEntries(colCount) {} /// returns false if all entries are zero bool takeModulus(const SparseMatrix::Scalar modulus) { ScalarProductSum bitwiseOr = 0; // bitwise or of all entries after modulus const auto end = mEntries.end(); for (auto it = mEntries.begin(); it != end; ++it) { if (*it >= modulus) *it = modulusOf(*it, modulus); bitwiseOr |= *it; } return bitwiseOr != 0; } size_t colCount() const {return mEntries.size();} bool empty() const {return mEntries.empty();} void clear(size_t colCount = 0) { mEntries.clear(); mEntries.resize(colCount); } ScalarProductSum& operator[](size_t col) { MATHICGB_ASSERT(col < colCount()); return mEntries[col]; } ScalarProductSum const& operator[](size_t col) const { MATHICGB_ASSERT(col < colCount()); return mEntries[col]; } void appendTo(SparseMatrix& matrix) {matrix.appendRow(mEntries);} void makeUnitary(const SparseMatrix::Scalar modulus, const size_t lead) { MATHICGB_ASSERT(lead < colCount()); MATHICGB_ASSERT(mEntries[lead] != 0); const auto end = mEntries.end(); auto it = mEntries.begin() + lead; const auto toInvert = static_cast(*it % modulus); const auto multiply = modularInverse(toInvert, modulus); *it = 1; for (++it; it != end; ++it) { const auto entry = modulusOf(*it, modulus); if (entry != 0) *it = modulusOf(product(entry, multiply), modulus); else *it = 0; } } void addRow(const SparseMatrix& matrix, SparseMatrix::RowIndex row) { MATHICGB_ASSERT(row < matrix.rowCount()); const auto end = matrix.rowEnd(row); for (auto it = matrix.rowBegin(row); it != end; ++it) { MATHICGB_ASSERT(it.index() < colCount()); add(it.scalar(), mEntries[it.index()]); } } template void addRowMultiple( const SparseMatrix::Scalar multiple, const Iter begin, const Iter end ) { // I have a matrix reduction that goes from 2.8s to 2.4s on MSVC 2012 by // using entries instead of mEntries, even after removing restrict and // const from entries. That does not make sense to me, but it is a fact // none-the-less, so don't replace entries by mEntries unless you think // it's worth a 14% slowdown of matrix reduction (the whole computation, // not just this method). ScalarProductSum* const MATHICGB_RESTRICT entries = mEntries.data(); #ifdef MATHICGB_DEBUG // These asserts are separated out since otherwise they would also need // to be duplicated due to the manual unrolling. for (auto it = begin; it != end; ++it) { MATHICGB_ASSERT(it.index() < colCount()); MATHICGB_ASSERT(entries + it.index() == &mEntries[it.index()]); } #endif // I have a matrix reduction that goes from 2.601s to 2.480s on MSVC 2012 // by unrolling this loop manually. Unrolling more than once was not a // benefit. So don't undo the unrolling unless you think it's worth a 5% // slowdown of matrix reduction (the whole computation, not just this // method). auto it = begin; if (std::distance(begin, end) % 2 == 1) { // Replacing this by a goto into the middle of the following loop // (similar to Duff's device) made the code slower on MSVC 2012. multiplyAdd(it.scalar(), multiple, entries[it.index()]); ++it; } while (it != end) { multiplyAdd(it.scalar(), multiple, entries[it.index()]); ++it; multiplyAdd(it.scalar(), multiple, entries[it.index()]); ++it; } } void rowReduceByUnitary( const SparseMatrix::RowIndex pivotRow, const SparseMatrix& matrix, const SparseMatrix::Scalar modulus ) { MATHICGB_ASSERT(matrix.rowBegin(pivotRow).scalar() == 1); // unitary MATHICGB_ASSERT(modulus > 1); auto begin = matrix.rowBegin(pivotRow); const auto col = begin.index(); const auto entry = modulusOf(mEntries[col], modulus); mEntries[col] = 0; if (entry == 0) return; ++begin; // can skip first entry as we just set it to zero. addRowMultiple( modularNegativeNonZero(entry, modulus), begin, matrix.rowEnd(pivotRow) ); } private: std::vector mEntries; }; SparseMatrix reduce( const QuadMatrix& qm, SparseMatrix::Scalar modulus ) { const SparseMatrix& toReduceLeft = qm.bottomLeft; const SparseMatrix& toReduceRight = qm.bottomRight; const SparseMatrix& reduceByLeft = qm.topLeft; const SparseMatrix& reduceByRight = qm.topRight; const auto leftColCount = qm.computeLeftColCount(); const auto rightColCount = static_cast(qm.computeRightColCount()); MATHICGB_ASSERT(leftColCount == reduceByLeft.rowCount()); const auto pivotCount = leftColCount; const auto rowCount = toReduceLeft.rowCount(); // ** pre-calculate what rows are pivots for what columns. // Store column indexes instead of row indices as the matrix is square // anyway (so all indices fit) and we are going to store this as a column // index later on. std::vector rowThatReducesCol(pivotCount); #ifdef MATHICGB_DEBUG // fill in an invalid value that can be recognized by asserts to be invalid. std::fill(rowThatReducesCol.begin(), rowThatReducesCol.end(), pivotCount); #endif for (SparseMatrix::ColIndex pivot = 0; pivot < pivotCount; ++pivot) { MATHICGB_ASSERT(!reduceByLeft.emptyRow(pivot)); SparseMatrix::ColIndex col = reduceByLeft.leadCol(pivot); MATHICGB_ASSERT(rowThatReducesCol[col] == pivotCount); rowThatReducesCol[col] = pivot; } #ifdef MATHICGB_DEBUG for (SparseMatrix::ColIndex col = 0; col < pivotCount; ++col) { MATHICGB_ASSERT(rowThatReducesCol[col] < pivotCount); } #endif SparseMatrix reduced(qm.topRight.memoryQuantum()); mgb::mtbb::enumerable_thread_specific denseRowPerThread([&](){ return DenseRow(); }); SparseMatrix tmp(qm.topRight.memoryQuantum()); std::vector rowOrder(rowCount); mgb::mtbb::mutex lock; mgb::mtbb::parallel_for(mgb::mtbb::blocked_range(0, rowCount, 2), [&](const mgb::mtbb::blocked_range& range) { auto& denseRow = denseRowPerThread.local(); for (auto it = range.begin(); it != range.end(); ++it) { const auto row = it; denseRow.clear(leftColCount); denseRow.addRow(toReduceLeft, row); MATHICGB_ASSERT(leftColCount == pivotCount); for (size_t pivot = 0; pivot < pivotCount; ++pivot) { if (denseRow[pivot] != 0) { auto entry = denseRow[pivot]; entry %= modulus; if (entry == 0) { denseRow[pivot] = 0; } else { entry = modulus - entry; const auto row = rowThatReducesCol[pivot]; MATHICGB_ASSERT(row < pivotCount); MATHICGB_ASSERT(!reduceByLeft.emptyRow(row)); MATHICGB_ASSERT(reduceByLeft.leadCol(row) == pivot); MATHICGB_ASSERT(entry < std::numeric_limits::max()); denseRow.addRowMultiple( static_cast(entry), ++reduceByLeft.rowBegin(row), reduceByLeft.rowEnd(row) ); denseRow[pivot] = entry; } } } mgb::mtbb::mutex::scoped_lock lockGuard(lock); for (size_t pivot = 0; pivot < pivotCount; ++pivot) { MATHICGB_ASSERT(denseRow[pivot] < std::numeric_limits::max()); if (denseRow[pivot] != 0) tmp.appendEntry(rowThatReducesCol[pivot], static_cast(denseRow[pivot])); } tmp.rowDone(); rowOrder[tmp.rowCount() - 1] = row; } }); mgb::mtbb::parallel_for(mgb::mtbb::blocked_range(0, rowCount), [&](const mgb::mtbb::blocked_range& range) {for (auto iter = range.begin(); iter != range.end(); ++iter) { const auto i = iter; const auto row = rowOrder[i]; auto& denseRow = denseRowPerThread.local(); denseRow.clear(rightColCount); denseRow.addRow(toReduceRight, row); auto it = tmp.rowBegin(i); const auto end = tmp.rowEnd(i); for (; it != end; ++it) { const auto begin = reduceByRight.rowBegin(it.index()); const auto end = reduceByRight.rowEnd(it.index()); denseRow.addRowMultiple(it.scalar(), begin, end); } mgb::mtbb::mutex::scoped_lock lockGuard(lock); bool zero = true; for (SparseMatrix::ColIndex col = 0; col < rightColCount; ++col) { const auto entry = static_cast(denseRow[col] % modulus); if (entry != 0) { reduced.appendEntry(col, entry); zero = false; } } if (!zero) reduced.rowDone(); }}); return std::move(reduced); } SparseMatrix reduceToEchelonFormSparse( const SparseMatrix& toReduce, const SparseMatrix::Scalar modulus ) { const auto colCount = toReduce.computeColCount(); const auto noRow = static_cast(-1); // pivotRowOfCol[i] is the pivot in column i or noRow // if we have not identified such a pivot so far. std::vector pivotRowOfCol(colCount, noRow); DenseRow rowToReduce(colCount); // ** Reduce to row echelon form -- every row is a pivot row. SparseMatrix pivots(colCount); for (SparseMatrix::RowIndex row = 0; row < toReduce.rowCount(); ++row) { if (toReduce.emptyRow(row)) continue; rowToReduce.clear(colCount); rowToReduce.addRow(toReduce, row); SparseMatrix::ColIndex leadingCol = 0; while (true) { // reduce row by previous pivots for (; leadingCol < colCount; ++leadingCol) { auto& entry = rowToReduce[leadingCol]; if (entry != 0) { entry %= modulus; if (entry != 0) break; } } if (leadingCol == colCount) break; // The row has been reduced to zero. const auto pivotRow = pivotRowOfCol[leadingCol]; if (pivotRow == noRow) { // If the row is a new pivot. rowToReduce.makeUnitary(modulus, leadingCol); pivotRowOfCol[leadingCol] = pivots.rowCount(); rowToReduce.appendTo(pivots); break; } rowToReduce.rowReduceByUnitary(pivotRow, pivots, modulus); } } // ** Reduce from row echelon form to reduced row echelon form SparseMatrix reduced(colCount); auto pivotCol = colCount; // Reduce pivot rows in descending order of leading column. The reduced // pivots go into reduced and we update pivotRowOfCol to refer to the // row indices in reduced as we go along. while (pivotCol != 0) { --pivotCol; const auto row = pivotRowOfCol[pivotCol]; if (row == noRow) continue; rowToReduce.clear(colCount); rowToReduce.addRow(pivots, row); MATHICGB_ASSERT(rowToReduce[pivotCol] == 1); // unitary for (auto col = pivotCol + 1; col != colCount; ++col) { auto& entry = rowToReduce[col]; if (entry == 0) continue; entry %= modulus; if (entry == 0) continue; const auto pivotRow = pivotRowOfCol[col]; if (pivotRow != noRow) rowToReduce.rowReduceByUnitary(pivotRow, reduced, modulus); MATHICGB_ASSERT(entry < modulus); } pivotRowOfCol[pivotCol] = reduced.rowCount(); rowToReduce.appendTo(reduced); } return std::move(reduced); } SparseMatrix reduceToEchelonForm( const SparseMatrix& toReduce, const SparseMatrix::Scalar modulus ) { const auto colCount = toReduce.computeColCount(); const auto rowCount = toReduce.rowCount(); // convert to dense representation std::vector dense(rowCount); mgb::mtbb::parallel_for(mgb::mtbb::blocked_range(0, rowCount), [&](const mgb::mtbb::blocked_range& range) {for (auto it = range.begin(); it != range.end(); ++it) { const auto row = it; if (toReduce.emptyRow(row)) continue; dense[row].clear(colCount); dense[row].addRow(toReduce, row); }}); // invariant: all columns in row to the left of leadCols[row] are zero. std::vector leadCols(rowCount); // pivot rows get copied here before being used to reduce the matrix. SparseMatrix reduced(toReduce.memoryQuantum()); // (col,row) in nextReducers, then use row as a pivot in column col // for the next iteration. std::vector< std::pair > nextReducers; // isPivotRow[row] is true if row is or has been used as a pivot. std::vector isPivotRow(rowCount); // columnHasPivot[col] is true if a pivot row for column col has // been chosen. std::vector columnHasPivot(colCount); bool firstIteration = true; while (firstIteration || reduced.rowCount() > 0) { firstIteration = false; size_t const reducerCount = reduced.rowCount(); //std::cout << "reducing " << reduced.rowCount() << " out of " << toReduce.rowCount() << std::endl; mgb::mtbb::mutex lock; mgb::mtbb::parallel_for(mgb::mtbb::blocked_range(0, rowCount), [&](const mgb::mtbb::blocked_range& range) {for (auto it = range.begin(); it != range.end(); ++it) { const auto row = it; MATHICGB_ASSERT(leadCols[row] <= colCount); DenseRow& denseRow = dense[row]; if (denseRow.empty()) continue; // reduce by each row of reduced. for (SparseMatrix::RowIndex reducerRow = 0; reducerRow < reducerCount; ++reducerRow) { const auto col = reduced.rowBegin(reducerRow).index(); if (denseRow[col] == 0 || (isPivotRow[row] && col == leadCols[row])) continue; denseRow.rowReduceByUnitary(reducerRow, reduced, modulus); } // update leadCols[row] SparseMatrix::ColIndex col; MATHICGB_ASSERT(leadCols[row] <= colCount); for (col = leadCols[row]; col < colCount; ++col) { denseRow[col] %= modulus; if (denseRow[col] != 0) break; } leadCols[row] = col; MATHICGB_ASSERT(leadCols[row] <= colCount); // note if we have found a new pivot row if (col == colCount) denseRow.clear(); else { MATHICGB_ASSERT(col < colCount); bool isNewReducer = false; { mgb::mtbb::mutex::scoped_lock lockGuard(lock); if (!columnHasPivot[col]) { columnHasPivot[col] = true; isNewReducer = true; nextReducers.push_back(std::make_pair(col, row)); } } if (isNewReducer) denseRow.makeUnitary(modulus, col); } }}); reduced.clear(); std::sort(nextReducers.begin(), nextReducers.end()); for (size_t i = 0; i < nextReducers.size(); ++i) { size_t const row = nextReducers[i].second; MATHICGB_ASSERT(static_cast (columnHasPivot[nextReducers[i].first])); MATHICGB_ASSERT(dense[row].colCount() == colCount); MATHICGB_ASSERT(dense[row][nextReducers[i].first] == 1); MATHICGB_ASSERT(reduced.rowCount() == i); MATHICGB_ASSERT(!isPivotRow[row]); dense[row].appendTo(reduced); // already unitary isPivotRow[row] = true; } nextReducers.clear(); } mgb::mtbb::parallel_for(mgb::mtbb::blocked_range(0, rowCount), [&](const mgb::mtbb::blocked_range& range) {for (auto it = range.begin(); it != range.end(); ++it) { const size_t row = it; dense[row].takeModulus(modulus); }}); #ifdef MATHICGB_DEBUG std::vector sawPivot(colCount); for (SparseMatrix::RowIndex row = 0; row < rowCount; ++row) { if (dense[row].empty()) { MATHICGB_ASSERT(!isPivotRow[row]); MATHICGB_ASSERT(leadCols[row] == colCount); } else { MATHICGB_ASSERT(isPivotRow[row]); const auto leadCol = leadCols[row]; MATHICGB_ASSERT(leadCol < colCount); MATHICGB_ASSERT(columnHasPivot[leadCol]); MATHICGB_ASSERT(dense[row][leadCol] == 1); MATHICGB_ASSERT(!sawPivot[leadCol]); sawPivot[leadCol] = true; for (size_t col = 0; col < colCount; ++col) { const auto scalar = dense[row][col]; if (col < leadCol) { MATHICGB_ASSERT(scalar == 0); } else if (col == leadCol) { MATHICGB_ASSERT(scalar == 1); } else { MATHICGB_ASSERT(scalar == 0 || !columnHasPivot[col]); } } } } #endif reduced.clear(); for (size_t row = 0; row < rowCount; ++row) if (!dense[row].empty()) dense[row].appendTo(reduced); return std::move(reduced); } } void addRowMultipleInplace( std::vector< std::vector >& matrix, const SparseMatrix::RowIndex addRow, const SparseMatrix::Scalar multiple, const SparseMatrix::RowIndex row, const SparseMatrix::ColIndex leadingCol, const SparseMatrix::ColIndex colCount, const SparseMatrix::Scalar modulus ) { assert(addRow < matrix.size()); assert(row < matrix.size()); assert(row != addRow); assert(leadingCol < colCount); assert(matrix[row].size() == colCount); assert(matrix[addRow].size() == colCount); for(auto col = leadingCol; col < colCount; ++col){ const auto product = modularProduct (multiple, matrix[addRow][col], modulus); matrix[row][col] = modularSum(matrix[row][col], product, modulus); } } void makeRowUnitary( std::vector< std::vector>& matrix, const SparseMatrix::RowIndex row, const SparseMatrix::ColIndex colCount, const SparseMatrix::ColIndex leadingCol, const SparseMatrix::Scalar modulus ) { assert(row 1); const auto leadingScalar = matrix[row][leadingCol]; assert(leadingScalar != 0); auto multiply = modularInverse(leadingScalar, modulus); for(SparseMatrix::ColIndex col = leadingCol; col < colCount; ++col) matrix[row][col] = modularProduct(matrix[row][col], multiply, modulus); } SparseMatrix::ColIndex leadingColumn( const std::vector< std::vector>& matrix, const SparseMatrix::RowIndex row, const SparseMatrix::ColIndex colCount, SparseMatrix::ColIndex startAtCol ) { assert(row < matrix.size()); assert(matrix[row].size() == colCount); for(auto col = startAtCol; col < colCount; ++col){ if(matrix[row][col] != 0) return col; } return colCount; } void rowReducedEchelonMatrix( std::vector< std::vector >& matrix, const SparseMatrix::ColIndex colCount, const SparseMatrix::Scalar modulus ) { assert(matrix.empty() || matrix[0].size() == colCount); const SparseMatrix::RowIndex rowCount = static_cast(matrix.size()); // pivotRowOfCol[i] is the pivot in column i or rowCount // if we have not identified such a pivot so far. std::vector pivotRowOfCol(colCount, rowCount); // row reduce to row echelon form for(SparseMatrix::RowIndex row=0; row> matrix(rowCount); for (SparseMatrix::RowIndex row = 0; row < rowCount; ++row) { MATHICGB_ASSERT(!toReduce.emptyRow(row)); matrix[row].resize(colCount); const auto end = toReduce.rowEnd(row); for (auto it = toReduce.rowBegin(row); it != end; ++it) { MATHICGB_ASSERT(it.index() < colCount); matrix[row][it.index()] = it.scalar(); } } rowReducedEchelonMatrix(matrix, colCount, modulus); // convert reduced matrix to SparseMatrix. SparseMatrix reduced; for (size_t row = 0; row < rowCount; ++row) { bool rowIsZero = true; for (SparseMatrix::ColIndex col = 0; col < colCount; ++col) { if (matrix[row][col] != 0) { rowIsZero = false; reduced.appendEntry(col, matrix[row][col]); } } if (!rowIsZero) reduced.rowDone(); } return std::move(reduced); } SparseMatrix reduceToEchelonFormShrawanDelayedModulus( const SparseMatrix& toReduce, SparseMatrix::Scalar modulus ) { const SparseMatrix::RowIndex rowCount = toReduce.rowCount(); const auto colCount = toReduce.computeColCount(); // Convert input matrix to dense format std::vector< std::vector> matrix(rowCount); for (SparseMatrix::RowIndex row = 0; row < rowCount; ++row) { MATHICGB_ASSERT(!toReduce.emptyRow(row)); matrix[row].resize(colCount); const auto end = toReduce.rowEnd(row); for (auto it = toReduce.rowBegin(row); it != end; ++it) { MATHICGB_ASSERT(it.index() < colCount); matrix[row][it.index()] = it.scalar(); } } rowReducedEchelonMatrix(matrix, colCount, modulus); // convert reduced matrix to SparseMatrix. SparseMatrix reduced; for (size_t row = 0; row < rowCount; ++row) { bool rowIsZero = true; for (SparseMatrix::ColIndex col = 0; col < colCount; ++col) { if (matrix[row][col] != 0) { rowIsZero = false; reduced.appendEntry(col, matrix[row][col]); } } if (!rowIsZero) reduced.rowDone(); } return std::move(reduced); } SparseMatrix F4MatrixReducer::reduceToBottomRight(const QuadMatrix& matrix) { MATHICGB_ASSERT(matrix.debugAssertValid()); MATHICGB_LOG_TIME(F4MatReduceTop); MATHICGB_LOG_TIME(F4MatrixReduce) << "\n***** Reducing QuadMatrix to bottom right matrix *****\n"; MATHICGB_IF_STREAM_LOG(F4MatrixReduce) {matrix.printStatistics(log.stream());}; return reduce(matrix, mModulus); } SparseMatrix F4MatrixReducer::reducedRowEchelonForm( const SparseMatrix& matrix ) { MATHICGB_LOG_TIME(F4RedBottomRight); MATHICGB_LOG_TIME(F4MatrixReduce) << "\n***** Reducing SparseMatrix to reduced row echelon form *****\n"; MATHICGB_IF_STREAM_LOG(F4MatrixReduce) {matrix.printStatistics(log.stream());}; const bool useShrawan = false; const bool useDelayedModulus = false; if (useShrawan) { if (useDelayedModulus) return reduceToEchelonFormShrawanDelayedModulus(matrix, mModulus); else return reduceToEchelonFormShrawan(matrix, mModulus); } else { // todo: actually do some work to find a good way to determine // when to use the sparse method, or alternatively make some // sort of hybrid. if (matrix.computeDensity() < 0.02) return reduceToEchelonFormSparse(matrix, mModulus); else return reduceToEchelonForm(matrix, mModulus); } } SparseMatrix F4MatrixReducer::reducedRowEchelonFormBottomRight( const QuadMatrix& matrix ) { return reducedRowEchelonForm(reduceToBottomRight(matrix)); } namespace { /// this has to be a separate function that returns the scalar since signed /// overflow is undefine behavior so we cannot check after the cast and /// we also cannot set the modulus field inside the constructor since it is /// const. SparseMatrix::Scalar checkModulus(const coefficient modulus) { // this assert has to be NO_ASSUME as otherwise the branch below will get // optimized out. MATHICGB_ASSERT_NO_ASSUME(modulus <= std::numeric_limits::max()); if (modulus > std::numeric_limits::max()) throw std::overflow_error("Too large modulus in F4 matrix reduction."); return static_cast(modulus); } } F4MatrixReducer::F4MatrixReducer(const coefficient modulus): mModulus(checkModulus(modulus)) {} MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/F4MatrixReducer.hpp000077500000000000000000000031101311555162500221550ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_F4_MATRIX_REDUCER_GUARD #define MATHICGB_F4_MATRIX_REDUCER_GUARD #include "SparseMatrix.hpp" MATHICGB_NAMESPACE_BEGIN class QuadMatrix; class PolyRing; /// Class that reduces an F4 matrix represented as a QuadMatrix. The /// answer that you get is the submatrix that contains new pivots. /// /// All QuadMatrix parameters passed into methods on this class are /// assumed to have a permutation of the top rows and left columns so /// that the top left matrix is upper unitriangular. In this way the /// lower left part of the matrix becomes all-zero after row reduction. class F4MatrixReducer { public: /// The ring used is Z/pZ where modulus is the prime p. F4MatrixReducer(coefficient modulus); /// Reduces the bottom rows by the top rows and returns the bottom right /// submatrix of the resulting quad matrix. The lower left submatrix /// is not returned because it is always zero after row reduction. SparseMatrix reduceToBottomRight(const QuadMatrix& matrix); /// Returns the reduced row echelon form of matrix. SparseMatrix reducedRowEchelonForm(const SparseMatrix& matrix); /// Returns the lower right submatrix of the reduced row echelon /// form of matrix. The lower left part is not returned because it is /// always zero after row reduction. SparseMatrix reducedRowEchelonFormBottomRight(const QuadMatrix& matrix); private: const SparseMatrix::Scalar mModulus; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/F4ProtoMatrix.cpp000077500000000000000000000042641311555162500216750ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "F4ProtoMatrix.hpp" MATHICGB_NAMESPACE_BEGIN auto F4ProtoMatrix::row(const RowIndex row) const -> Row { MATHICGB_ASSERT(row < mRows.size()); const auto& r = mRows[row]; Row rr; rr.indices = mIndices.data() + r.indicesBegin; rr.entryCount = r.entryCount; if (!r.scalarsStoredExternally) { rr.scalars = mScalars.data() + r.scalarsBegin; } else { rr.scalars = nullptr; rr.externalScalars = r.externalScalars; } return rr; } auto F4ProtoMatrix::makeRowWithTheseScalars(const Poly& scalars) -> ColIndex* { MATHICGB_ASSERT(rowCount() < std::numeric_limits::max()); MATHICGB_ASSERT(scalars.termCount() < std::numeric_limits::max()); InternalRow row; row.indicesBegin = mIndices.size(); row.scalarsBegin = std::numeric_limits::max(); row.entryCount = static_cast(scalars.termCount()); row.scalarsStoredExternally = true; row.externalScalars = scalars.coefBegin(); mRows.push_back(row); mIndices.resize(mIndices.size() + row.entryCount); return mIndices.data() + row.indicesBegin; } auto F4ProtoMatrix::makeRow(ColIndex entryCount) -> std::pair { MATHICGB_ASSERT(rowCount() < std::numeric_limits::max()); InternalRow row; row.indicesBegin = mIndices.size(); row.scalarsBegin = mScalars.size(); row.entryCount = entryCount; row.scalarsStoredExternally = false; mRows.push_back(row); mIndices.resize(mIndices.size() + entryCount); mScalars.resize(mScalars.size() + entryCount); return std::make_pair( mIndices.data() + row.indicesBegin, mScalars.data() + row.scalarsBegin ); } void F4ProtoMatrix::removeLastEntries(const RowIndex row, const ColIndex count) { MATHICGB_ASSERT(row < rowCount()); MATHICGB_ASSERT(mRows[row].entryCount >= count); mRows[row].entryCount -= count; if (row != rowCount() - 1) return; mIndices.resize(mIndices.size() - count); if (!mRows[row].scalarsStoredExternally) mScalars.resize(mScalars.size() - count); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/F4ProtoMatrix.hpp000077500000000000000000000025751311555162500217050ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_F4_PROTO_MATRIX_GUARD #define MATHICGB_F4_PROTO_MATRIX_GUARD #include "PolyRing.hpp" #include "SparseMatrix.hpp" #include "Poly.hpp" MATHICGB_NAMESPACE_BEGIN class F4ProtoMatrix { public: typedef uint32 RowIndex; typedef uint32 ColIndex; typedef SparseMatrix::Scalar Scalar; typedef coefficient ExternalScalar; typedef Poly::ConstCoefIterator ExternalConstCoefIterator; struct Row { Row(): indices(), scalars(), externalScalars(), entryCount() {} const ColIndex* indices; const Scalar* scalars; ExternalConstCoefIterator externalScalars; ColIndex entryCount; }; RowIndex rowCount() const {return static_cast(mRows.size());} Row row(const RowIndex row) const; ColIndex* makeRowWithTheseScalars(const Poly& scalars); std::pair makeRow(ColIndex entryCount); void removeLastEntries(const RowIndex row, const ColIndex count); private: struct InternalRow { size_t indicesBegin; size_t scalarsBegin; ColIndex entryCount; bool scalarsStoredExternally; ExternalConstCoefIterator externalScalars; }; std::vector mIndices; std::vector mScalars; std::vector mRows; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/F4Reducer.cpp000077500000000000000000000241071311555162500207740ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "F4Reducer.hpp" #include "F4MatrixBuilder.hpp" #include "F4MatrixBuilder2.hpp" #include "F4MatrixReducer.hpp" #include "QuadMatrix.hpp" #include "LogDomain.hpp" #include "CFile.hpp" #include #include MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixRows, "Count number of rows in F4 matrices." ); MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixTopRows, "Count number of top (reducer) rows in F4 matrices." ); MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixBottomRows, "Count number of bottom (reducee) rows in F4 matrices." ); MATHICGB_DEFINE_LOG_DOMAIN( F4MatrixEntries, "Count number of non-zero entries in F4 matrices." ); MATHICGB_DEFINE_LOG_ALIAS( "F4Detail", "F4MatrixEntries,F4MatrixBottomRows,F4MatrixTopRows,F4MatrixRows," "F4MatrixReduce,F4" ); MATHICGB_DEFINE_LOG_ALIAS( "F4", "F4MatrixSizes,F4MatrixBuild,F4MatrixBuild2," "F4MatReduceTop,F4RedBottomRight" ); #include "Reducer.hpp" #include "PolyRing.hpp" #include MATHICGB_NAMESPACE_BEGIN void f4ReducerDependency() {} class F4Reducer : public Reducer { public: enum Type { OldType, NewType }; F4Reducer(const PolyRing& ring, Type type); virtual unsigned int preferredSetSize() const; /// Store all future matrices to file-1.mat, file-2.mat and so on. /// Matrices with less than minEntries non-zero entries are not stored. /// If file is an empty string then no matrices are stored. If this method /// is never called then no matrices are stored. void writeMatricesTo(std::string file, size_t minEntries); virtual std::unique_ptr classicReduce (const Poly& poly, const PolyBasis& basis); virtual std::unique_ptr classicTailReduce (const Poly& poly, const PolyBasis& basis); virtual std::unique_ptr classicReduceSPoly (const Poly& a, const Poly& b, const PolyBasis& basis); virtual void classicReduceSPolySet( std::vector >& spairs, const PolyBasis& basis, std::vector >& reducedOut ); virtual void classicReducePolySet( const std::vector >& polys, const PolyBasis& basis, std::vector >& reducedOut ); virtual std::unique_ptr regularReduce( ConstMonoRef sig, ConstMonoRef multiple, size_t basisElement, const SigPolyBasis& basis ); virtual void setMemoryQuantum(size_t quantum); virtual std::string description() const; virtual size_t getMemoryUse() const; const PolyRing& ring() const {return mRing;} const Monoid& monoid() const {return mRing.monoid();} private: void saveMatrix(const QuadMatrix& matrix); Type mType; std::unique_ptr mFallback; const PolyRing& mRing; size_t mMemoryQuantum; std::string mStoreToFile; /// stem of file names to save matrices to size_t mMinEntryCountForStore; /// don't save matrices with fewer entries size_t mMatrixSaveCount; // how many matrices have been saved }; F4Reducer::F4Reducer(const PolyRing& ring, Type type): mType(type), mFallback(Reducer::makeReducer(Reducer::Reducer_Geobucket_Hashed, ring)), mRing(ring), mMemoryQuantum(0), mStoreToFile(""), mMinEntryCountForStore(0), mMatrixSaveCount(0) { } unsigned int F4Reducer::preferredSetSize() const { return 100000; } void F4Reducer::writeMatricesTo(std::string file, size_t minEntries) { mStoreToFile = std::move(file); mMinEntryCountForStore = minEntries; mMatrixSaveCount = 0; } std::unique_ptr F4Reducer::classicReduce (const Poly& poly, const PolyBasis& basis) { if (tracingLevel >= 2) std::cerr << "F4Reducer: Using fall-back reducer for single classic reduction\n"; return mFallback->classicReduce(poly, basis); } std::unique_ptr F4Reducer::classicTailReduce (const Poly& poly, const PolyBasis& basis) { if (tracingLevel >= 2) std::cerr << "F4Reducer: Using fall-back reducer for single classic tail reduction\n"; return mFallback->classicTailReduce(poly, basis); } std::unique_ptr F4Reducer::classicReduceSPoly( const Poly& a, const Poly& b, const PolyBasis& basis ) { if (tracingLevel >= 2) std::cerr << "F4Reducer: " "Using fall-back reducer for single classic S-pair reduction\n"; return mFallback->classicReduceSPoly(a, b, basis); } void F4Reducer::classicReduceSPolySet( std::vector>& spairs, const PolyBasis& basis, std::vector>& reducedOut ) { if (spairs.size() <= 1) { if (tracingLevel >= 2) std::cerr << "F4Reducer: Using fall-back reducer for " << spairs.size() << " S-pairs.\n"; mFallback->classicReduceSPolySet(spairs, basis, reducedOut); return; } reducedOut.clear(); MATHICGB_ASSERT(!spairs.empty()); if (tracingLevel >= 2) std::cerr << "F4Reducer: Reducing " << spairs.size() << " S-polynomials.\n"; SparseMatrix reduced; QuadMatrix::Monomials monomials; { QuadMatrix qm(basis.ring()); { if (mType == OldType) { F4MatrixBuilder builder(basis, mMemoryQuantum); for (const auto& spair : spairs) builder.addSPolynomialToMatrix (basis.poly(spair.first), basis.poly(spair.second)); builder.buildMatrixAndClear(qm); } else { F4MatrixBuilder2 builder(basis, mMemoryQuantum); for (const auto& spair : spairs) builder.addSPolynomialToMatrix (basis.poly(spair.first), basis.poly(spair.second)); builder.buildMatrixAndClear(qm); } } MATHICGB_LOG_INCREMENT_BY(F4MatrixRows, qm.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixTopRows, qm.topLeft.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixBottomRows, qm.bottomLeft.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixEntries, qm.entryCount()); saveMatrix(qm); reduced = F4MatrixReducer(basis.ring().charac()). reducedRowEchelonFormBottomRight(qm); monomials = std::move(qm.rightColumnMonomials); for (auto& mono : qm.leftColumnMonomials) monoid().freeRaw(mono.castAwayConst()); } for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) { auto p = make_unique(basis.ring()); reduced.rowToPolynomial(row, monomials, *p); reducedOut.push_back(std::move(p)); } for (auto& mono : monomials) monoid().freeRaw(mono.castAwayConst()); } void F4Reducer::classicReducePolySet( const std::vector< std::unique_ptr >& polys, const PolyBasis& basis, std::vector< std::unique_ptr >& reducedOut ) { if (polys.size() <= 1) { if (tracingLevel >= 2) std::cerr << "F4Reducer: Using fall-back reducer for " << polys.size() << " polynomials.\n"; mFallback->classicReducePolySet(polys, basis, reducedOut); return; } reducedOut.clear(); MATHICGB_ASSERT(!polys.empty()); if (tracingLevel >= 2) std::cerr << "F4Reducer: Reducing " << polys.size() << " polynomials.\n"; SparseMatrix reduced; QuadMatrix::Monomials monomials; { QuadMatrix qm(ring()); { if (mType == OldType) { F4MatrixBuilder builder(basis, mMemoryQuantum); for (const auto& poly : polys) builder.addPolynomialToMatrix(*poly); builder.buildMatrixAndClear(qm); } else { F4MatrixBuilder2 builder(basis, mMemoryQuantum); for (const auto& poly : polys) builder.addPolynomialToMatrix(*poly); builder.buildMatrixAndClear(qm); } } MATHICGB_LOG_INCREMENT_BY(F4MatrixRows, qm.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixTopRows, qm.topLeft.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixBottomRows, qm.bottomLeft.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixEntries, qm.entryCount()); saveMatrix(qm); reduced = F4MatrixReducer(basis.ring().charac()). reducedRowEchelonFormBottomRight(qm); monomials = std::move(qm.rightColumnMonomials); for (auto& mono : qm.leftColumnMonomials) monoid().freeRaw(mono.castAwayConst()); } if (tracingLevel >= 2 && false) std::cerr << "F4Reducer: Extracted " << reduced.rowCount() << " non-zero rows\n"; for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) { auto p = make_unique(basis.ring()); reduced.rowToPolynomial(row, monomials, *p); reducedOut.push_back(std::move(p)); } for (auto& mono : monomials) monoid().freeRaw(mono.castAwayConst()); } std::unique_ptr F4Reducer::regularReduce( ConstMonoRef sig, ConstMonoRef multiple, size_t basisElement, const SigPolyBasis& basis ) { if (tracingLevel >= 2) std::cerr << "F4Reducer: Using fall-back reducer for single regular reduction\n"; auto p = mFallback->regularReduce(sig, multiple, basisElement, basis); return p; } void F4Reducer::setMemoryQuantum(size_t quantum) { mMemoryQuantum = quantum; } std::string F4Reducer::description() const { return "F4 reducer"; } size_t F4Reducer::getMemoryUse() const { return 0; // @todo: implement } void F4Reducer::saveMatrix(const QuadMatrix& matrix) { if (mStoreToFile.empty()) return; const auto entryCount = matrix.entryCount(); if (mMinEntryCountForStore > entryCount) return; ++mMatrixSaveCount; std::ostringstream fileName; fileName << mStoreToFile << '-' << mMatrixSaveCount << ".qmat"; if (tracingLevel > 2) std::cerr << "F4Reducer: Saving matrix to " << fileName.str() << '\n'; CFile file(fileName.str(), "wb"); matrix.write (static_cast(mRing.charac()), file.handle()); } std::unique_ptr makeF4Reducer( const PolyRing& ring, bool oldType, std::string file, size_t minEntries ) { auto reducer = oldType ? make_unique(ring, F4Reducer::OldType) : make_unique(ring, F4Reducer::NewType); reducer->writeMatricesTo(file, minEntries); return std::move(reducer); } MATHICGB_REGISTER_REDUCER( "F4Old", Reducer_F4_Old, (make_unique(ring, F4Reducer::OldType)) ); MATHICGB_REGISTER_REDUCER( "F4New", Reducer_F4_New, (make_unique(ring, F4Reducer::NewType)) ); MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/F4Reducer.hpp000077500000000000000000000014731311555162500210020ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_F4_REDUCER_GUARD #define MATHICGB_F4_REDUCER_GUARD #include MATHICGB_NAMESPACE_BEGIN class Reducer; class PolyRing; /// Create an F4 reducer with extra parameters for writing out the matrix. /// Set file to "" to disable writing of matrices. std::unique_ptr makeF4Reducer( const PolyRing& ring, bool oldType, std::string file, size_t minEntries ); // This translation unit has to expose something that is needed elsewhere. // Otherwise, the compiler will think it is not needed and exclude the // whole thing, despite there being important global objects in the .cpp file. void f4ReducerDependency(); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/FixedSizeMonomialMap.h000077500000000000000000000347441311555162500227120ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD #define MATHICGB_FIXED_SIZE_MONOMIAL_MAP_GUARD #include "Atomic.hpp" #include "mtbb.hpp" #include "PolyRing.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// Concurrent hashtable mapping from monomials to T with a fixed number of /// buckets. Lookups are lockless while insertions grab a lock. /// /// There is no limitation on the number of entries that can be inserted, /// but performance will suffer if the ratio of elements to buckets gets /// high. /// /// You can insert new values but you cannot change the value that an /// already-inserted value maps to. It is possible to clear the table /// but this operation is not safe for concurrency. template class FixedSizeMonomialMap { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef T mapped_type; typedef std::pair value_type; /// Iterates through entries in the hash table. class const_iterator; // Construct a hash table with at least requestedBucketCount buckets. There // may be more buckets. Currently the number is rounded up to the next power // of two. FixedSizeMonomialMap( const size_t requestedBucketCount, const PolyRing& ring ): mHashToIndexMask(computeHashMask(requestedBucketCount)), mBuckets( make_unique_array>(hashMaskToBucketCount(mHashToIndexMask)) ), mRing(ring), mNodeAlloc(Node::bytesPerNode(ring.monoid())) { // Calling new int[x] does not zero the array. std::atomic has a trivial // constructor so the same thing is true of new atomic[x]. Calling // new int[x]() is supposed to zero initialize but this apparently // does not work on GCC. So we have to fill the table with nulls // manually. This was wonderful to debug btw. // We can store relaxed as the constructor does not run concurrently. setTableEntriesToNullRelaxed(); } /// Construct a hash table with at least requestedBucketCount buckets and /// insert the elements from the parameter map. /// /// The parameter map remains a valid object that can satisfy queries. /// However, it is an error to call non-const methods on the map other /// than the destructor. Also, insertions into *this may or may not /// be reflected for queries into map and some of the entries currently /// in map will disappear. FixedSizeMonomialMap( const size_t requestedBucketCount, FixedSizeMonomialMap&& map ): mHashToIndexMask(computeHashMask(requestedBucketCount)), mBuckets( make_unique_array>(hashMaskToBucketCount(mHashToIndexMask)) ), mRing(map.ring()), mNodeAlloc(std::move(map.mNodeAlloc)) { // We can store relaxed as the constructor does not run concurrently. const auto relax = std::memory_order_relaxed; setTableEntriesToNullRelaxed(); const auto tableEnd = map.mBuckets.get() + map.bucketCount(); for (auto tableIt = map.mBuckets.get(); tableIt != tableEnd; ++tableIt) { for (Node* node = tableIt->load(); node != 0;) { const size_t index = hashToIndex(monoid().hash(node->mono())); const auto next = node->next(relax); node->setNext(mBuckets[index].load(relax), relax); mBuckets[index].store(node, relax); node = next; } } } /// Return how many buckets the hash table has. size_t bucketCount() const { return hashMaskToBucketCount(mHashToIndexMask); } const PolyRing& ring() const {return mRing;} const Monoid& monoid() const {return mRing.monoid();} /// The range [begin(), end()) contains all entries in the hash table. /// Insertions invalidate all iterators. Beware that insertions can /// happen concurrently. const_iterator begin() const { const auto bucketsBegin = mBuckets.get(); const auto bucketsEnd = bucketsBegin + bucketCount(); return const_iterator(bucketsBegin, bucketsEnd); } const_iterator end() const { const auto bucketsBegin = mBuckets.get(); const auto bucketsEnd = bucketsBegin + bucketCount(); return const_iterator(bucketsEnd, bucketsEnd); } /// Returns the value associated to mono or null if there is no such value. /// Also returns an internal monomial that equals mono if such a monomial /// exists. std::pair find(ConstMonoRef mono) const { const auto monoHash = monoid().hash(mono); const auto* node = bucketAtIndex(hashToIndex(monoHash)); for (; node != 0; node = node->next(std::memory_order_consume)) { // To my surprise, it seems to be faster to comment out this branch. // I guess the hash table has too few collisions to make it worth it. //if (monoHash != mRing.monomialHashValue(node->mono)) // continue; if (monoid().equalHintTrue(mono, node->mono())) return std::make_pair(&node->value, node->mono().ptr()); } return std::make_pair(nullptr, ConstMonoPtr()); } // As find on the product a*b but also returns the monomial that is the // product. MATHICGB_INLINE std::pair findProduct( ConstMonoRef a, ConstMonoRef b ) const { const HashValue abHash = monoid().hashOfProduct(a, b); const Node* node = bucketAtIndex(hashToIndex(abHash)); for (; node != 0; node = node->next(std::memory_order_consume)) { // To my surprise, it seems to be faster to comment out this branch. // I guess the hash table has too few collisions to make it worth it. //if (abHash != mRing.monomialHashValue(node->mono)) // continue; if (monoid().isProductOfHintTrue(a, b, node->mono())) return std::make_pair(&node->value, node->mono().ptr()); } return std::make_pair(nullptr, nullptr); } /// As findProduct but looks for a1*b and a2*b at one time. MATHICGB_INLINE std::pair findTwoProducts( ConstMonoRef a1, ConstMonoRef a2, ConstMonoRef b ) const { const HashValue a1bHash = monoid().hashOfProduct(a1, b); const HashValue a2bHash = monoid().hashOfProduct(a2, b); const Node* const node1 = bucketAtIndex(hashToIndex(a1bHash)); const Node* const node2 = bucketAtIndex(hashToIndex(a2bHash)); if ( node1 != 0 && node2 != 0 && monoid().isTwoProductsOfHintTrue (a1, a2, b, node1->mono(), node2->mono()) ) return std::make_pair(&node1->value, &node2->value); else return std::make_pair(findProduct(a1, b).first, findProduct(a2, b).first); } /// Makes value.first map to value.second unless value.first is already /// present in the map - in that case nothing is done. If p is the returned /// pair then *p.first.first is the value that value.first maps to after the insert /// and p.second is true if an insertion was performed. *p.first.first will not /// equal value.second if an insertion was not performed - unless the /// inserted value equals the already present value. /// /// p.first.second is a internal monomial that equals value.first. std::pair< std::pair, bool> insert(const value_type& value) { const mgb::mtbb::mutex::scoped_lock lockGuard(mInsertionMutex); // find() loads buckets with memory_order_consume, so it may seem like // we need some extra synchronization to make sure that we have the // most up to date view of the bucket that value.first goes in - // what if a pending insert is hiding in a cache of some other processor // somewhere? We in fact have an up to date view of every bucket in the // the table already because inserts only happen while holding the // insertion mutex and by locking that mutex we have synchronized with // all threads that previously did insertions. { const auto found = find(*value.first); if (found.first != 0) { auto p = std::make_pair(found.first, *found.second); return std::make_pair(p, false); // key already present } } const auto node = static_cast(mNodeAlloc.alloc()); const size_t index = hashToIndex(monoid().hash(*value.first)); // the constructor initializes the first field of node->mono, so // it has to be called before copying the monomial. new (node) Node(bucketAtIndex(index), value.second); monoid().copy(*value.first, node->mono()); // we cannot store with memory_order_relaxed here because unlocking the // lock only synchronizes with threads who later grab the lock - it does // not synchronize with reading threads since they do not grab the lock. mBuckets[index].store(node, std::memory_order_release); auto p = std::make_pair(&node->value, node->constMono()); return std::make_pair(p, true); // successful insertion } /// This operation removes all entries from the table. This operation /// requires synchronization with and mutual exclusion from all other /// clients of *this - you need to supply this synchronization manually. void clearNonConcurrent() { #ifdef MATHICGB_DEBUG // requires mutual exclusion from both readers and writers, but we can // only assert on this for the writers. if (mInsertionMutex.try_lock()) mInsertionMutex.unlock(); else { MATHICGB_ASSERT(false); } #endif // we can store relaxed as the client supplies synchronization. setTableEntriesToNullRelaxed(); // This is the reason that we cannot support this operation concurrently - // we have no way to know when it is safe to deallocate the monomials // since readers do no synchronization. mNodeAlloc.freeAllBuffers(); } private: void setTableEntriesToNullRelaxed() { const auto tableEnd = mBuckets.get() + bucketCount(); for (auto tableIt = mBuckets.get(); tableIt != tableEnd; ++tableIt) tableIt->store(0, std::memory_order_relaxed); } class Node { public: Node(Node* next, const mapped_type value): mNext(next), value(value) {} MonoRef mono() {return Monoid::toRef(mMono);} ConstMonoRef mono() const {return Monoid::toRef(mMono);} ConstMonoRef constMono() const {return Monoid::toRef(mMono);} Node* next(std::memory_order order) {return mNext.load(order);} const Node* next(std::memory_order order) const {return mNext.load(order);} void setNext(Node* next, std::memory_order order) { mNext.store(next, order); } const mapped_type value; static size_t bytesPerNode(const Monoid& monoid) { return sizeof(Node) + sizeof(exponent) * (monoid.entryCount() - 1); } private: Atomic mNext; exponent mMono[1]; }; static HashValue computeHashMask(const size_t requestedBucketCount) { // round request up to nearest power of 2. size_t pow2 = 1; while (pow2 < requestedBucketCount && 2 * pow2 != 0) pow2 *= 2; MATHICGB_ASSERT(pow2 > 0 && (pow2 & (pow2 - 1)) == 0); // power of two // If casting to a hash value overflows, then we get the maximum // possible number of buckets based on the range of the hash // value type. Only unsigned overflow is defined, so we need // to assert that the hash type is unsigned. static_assert(!std::numeric_limits::is_signed, ""); const auto hashToIndexMask = static_cast(pow2 - 1); MATHICGB_ASSERT(pow2 == hashMaskToBucketCount(hashToIndexMask)); return hashToIndexMask; } static size_t hashMaskToBucketCount(const HashValue mask) { const auto count = static_cast(mask) + 1u; // should be power of 2 MATHICGB_ASSERT(count > 0 && (count & (count - 1)) == 0); return count; } size_t hashToIndex(HashValue hash) const { const auto index = hash & mHashToIndexMask; MATHICGB_ASSERT(index == hash % bucketCount()); return index; } Node* bucketAtIndex(size_t index) { MATHICGB_ASSERT(index < bucketCount()); return mBuckets[index].load(std::memory_order_consume); } const Node* bucketAtIndex(size_t index) const { MATHICGB_ASSERT(index < bucketCount()); return mBuckets[index].load(std::memory_order_consume); } const HashValue mHashToIndexMask; std::unique_ptr[]> const mBuckets; const PolyRing& mRing; memt::BufferPool mNodeAlloc; // nodes are allocated from here. mgb::mtbb::mutex mInsertionMutex; public: class const_iterator { public: typedef std::forward_iterator_tag iterator_category; typedef std::pair value_type; typedef ptrdiff_t difference_type; typedef size_t distance_type; typedef value_type* pointer; typedef value_type& reference; const_iterator(): mNode(0), mBucket(0), mBucketsEnd(0) {} const_iterator& operator++() { MATHICGB_ASSERT(mNode != 0); MATHICGB_ASSERT(mBucket != mBucketsEnd); const Node* const node = mNode->next(std::memory_order_consume); if (node != 0) mNode = node; else advanceBucket(); return *this; } bool operator==(const const_iterator& it) const { MATHICGB_ASSERT(fromSameMap(it)); return mNode == it.mNode; } bool operator!=(const const_iterator& it) const { return !(*this == it); } const value_type operator*() const { MATHICGB_ASSERT(mNode != 0); return std::make_pair(mNode->value, mNode->mono()); } private: friend class FixedSizeMonomialMap; const_iterator( const Atomic* const bucketBegin, const Atomic* const bucketEnd ): mBucket(bucketBegin), mBucketsEnd(bucketEnd) { if (bucketBegin == bucketEnd) { mNode = 0; return; } const Node* const node = bucketBegin->load(std::memory_order_consume); if (node != 0) mNode = node; else advanceBucket(); } void advanceBucket() { MATHICGB_ASSERT(mBucket != mBucketsEnd); while (true) { ++mBucket; if (mBucket == mBucketsEnd) { mNode = 0; break; } const Node* const node = mBucket->load(std::memory_order_consume); if (node != 0) { mNode = node; break; } } } bool fromSameMap(const const_iterator& it) const { return mBucketsEnd == it.mBucketsEnd; } const Node* mNode; const Atomic* mBucket; const Atomic* mBucketsEnd; }; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/KoszulQueue.hpp000077500000000000000000000042761311555162500215170ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_KOSZUL_QUEUE_GUARD #define MATHICGB_KOSZUL_QUEUE_GUARD #include "PolyRing.hpp" #include "NonCopyable.hpp" #include MATHICGB_NAMESPACE_BEGIN /// Used to keep track of pending Koszul syzygy signatures in the signature /// basis algorithm. class KoszulQueue : public NonCopyable { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPool MonoPool; KoszulQueue(const Monoid& monoid): mPool(monoid), mQueue(Configuration(monoid, mPool)) {} KoszulQueue(KoszulQueue&& kq): mQueue(std::move(kq.mQueue)), mPool(std::move(kq.mPool)) {} ConstMonoRef top() const { MATHICGB_ASSERT(!empty()); return *mQueue.top(); } void pop() { MATHICGB_ASSERT(!empty()); mPool.freeRaw(*mQueue.pop()); } void push(ConstMonoRef sig) { auto m = mPool.alloc(); monoid().copy(sig, m); mQueue.push(m.release()); } bool empty() const {return mQueue.empty();} size_t size() const {return mQueue.size();} size_t getMemoryUse() const {return mQueue.getMemoryUse();} const Monoid& monoid() const {return mQueue.getConfiguration().monoid();} private: class Configuration { public: typedef Monoid::MonoPtr Entry; Configuration(const Monoid& monoid, MonoPool& pool): mMonoid(monoid), mPool(pool) {} typedef Monoid::CompareResult CompareResult; CompareResult compare(const Entry& a, const Entry& b) const { return monoid().compare(*a, *b); } bool cmpLessThan(CompareResult r) const {return r == Monoid::GreaterThan;} static const bool fastIndex = false; static const bool supportDeduplication = true; bool cmpEqual(CompareResult r) const {return r == Monoid::EqualTo;} Entry deduplicate(Entry a, Entry b) { mPool.freeRaw(*b); return a; } const Monoid& monoid() const {return mMonoid;} private: const Monoid& mMonoid; MonoPool& mPool; }; MonoPool mPool; mic::Heap mQueue; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/LogDomain.cpp000077500000000000000000000052651311555162500210660ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "LogDomain.hpp" #include "LogDomainSet.hpp" #include #include MATHICGB_NAMESPACE_BEGIN static const auto logDomainGlobalStartTime = mgb::mtbb::tick_count::now(); LogDomain::LogDomain( const char* const name, const char* const description, const bool enabled, const bool streamEnabled ): mEnabled(enabled), mOriginallyEnabled(enabled), mStreamEnabled(streamEnabled), mOriginallyStreamEnabled(streamEnabled), mName(name), mDescription(description), mInterval(), mHasTime(false), mCount(0), mHasCount(false) { LogDomainSet::singleton().registerLogDomain(*this); } void LogDomain::reset() { mEnabled = mOriginallyEnabled; mStreamEnabled = mOriginallyStreamEnabled; mInterval = TimeInterval(); mHasTime = false; mCount = 0; mHasCount = false; } std::ostream& LogDomain::stream() { return std::cerr; } LogDomain::Timer LogDomain::timer() { return Timer(*this); } double LogDomain::loggedSecondsReal() const { return mInterval.realSeconds; } void LogDomain::TimeInterval::print(std::ostream& out) const { const auto oldFlags = out.flags(); const auto oldPrecision = out.precision(); out.precision(3); out << std::fixed << realSeconds << "s (real)"; // todo: restore the stream state using RAII, since the above code might // throw an exception. out.precision(oldPrecision); out.flags(oldFlags); } void LogDomain::recordTime(TimeInterval interval) { if (!enabled()) return; mInterval.realSeconds += interval.realSeconds; mHasTime = true; if (streamEnabled()) { MATHICGB_ASSERT(mName != 0); stream() << mName << " time recorded: "; interval.print(stream()); stream() << std::endl; } } LogDomain::Timer::Timer(LogDomain& logger): mLogger(logger), mTimerRunning(false), mRealTicks() { start(); } LogDomain::Timer::~Timer() { stop(); } void LogDomain::Timer::stop() { if (!running()) return; mTimerRunning = false; if (!mLogger.enabled()) return; TimeInterval interval; interval.realSeconds = (mgb::mtbb::tick_count::now() - mRealTicks).seconds(); mLogger.recordTime(interval); return; } void LogDomain::Timer::start() { if (!mLogger.enabled() || mTimerRunning) return; mTimerRunning = true; mRealTicks = mgb::mtbb::tick_count::now(); } LogDomainInternal::LogAliasRegisterer::LogAliasRegisterer(const char* alias, const char* of) { LogDomainSet::singleton().registerLogAlias(alias, of); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/LogDomain.hpp000077500000000000000000000252001311555162500210620ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_LOG_DOMAIN_GUARD #define MATHICGB_LOG_DOMAIN_GUARD #include "mtbb.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN /// A named area of logging that can be turned on or off at runtime and at /// compile time. /// /// A logger that is turned off at compile time emits no code /// into the executable and all the code that writes to that logger is also /// removed by the optimizer if it is written in the correct way. Use the /// logging macroes to ensure proper use so that compile-time disabled /// LogDomains properly have zero overhead. LogDomains can be turned on /// and off at compile time and at runtime individually. /// /// Compile-time enabled loggers automatically register themselves at start-up /// with LogDomainSet::singleton(). /// /// @todo: support turning all loggers off globally with a macro, regardless /// of their individual compile-time on/off setting. template class LogDomain {}; template<> class LogDomain { public: static const bool compileTimeEnabled = true; LogDomain( const char* const name, const char* const description, const bool enabled, const bool streamEnabled ); const char* name() const {return mName;} const char* description() const {return mDescription;} bool enabled() const {return mEnabled;} bool streamEnabledPure() const {return mStreamEnabled;} bool streamEnabled() const {return enabled() && streamEnabledPure();} void setEnabled(const bool enabled) {mEnabled = enabled;} void setStreamEnabled(const bool enabled) {mStreamEnabled = enabled;} std::ostream& stream(); /// Class for recording time that is logged. Movable. class Timer; /// Returns a started timer. Timer timer(); /// Returns true if any time has been logged on this logger, even if the /// duration of that time was zero (that is., less than the resolution /// of the timer). bool hasTime() const {return mHasTime;} double loggedSecondsReal() const; typedef unsigned long long Counter; Counter count() const {return mCount;} void setCount(const Counter counter) { if (enabled()) { mCount = counter; mHasCount = true; } } /// Returns true if setCount has been called. bool hasCount() const {return mHasCount;} /// Resets this object to the state it had when it was /// constructed. void reset(); private: struct TimeInterval { // todo: support user time too. clock() doesn't seem to sum the time // for all threads, so that didn't work. double realSeconds; void print(std::ostream& out) const; }; void recordTime(TimeInterval interval); bool mEnabled; const bool mOriginallyEnabled; bool mStreamEnabled; const bool mOriginallyStreamEnabled; const char* mName; const char* mDescription; TimeInterval mInterval; /// Total amount of time recorded on this log. bool mHasTime; /// Whether any time has been registered (even if 0s). Counter mCount; bool mHasCount; /// Whether the count has been set (even if set to zero) }; class LogDomain::Timer { public: /// Start the timer running. The elapsed time will be logged to the logger /// once the timer is stopped or destructed. Timer(LogDomain& logger); /// Stops the timer. ~Timer(); /// Returns true if the timer is currently recording time. bool running() const {return mTimerRunning;} /// Stops recording time and logs the elapsed time to the logger. /// /// This is a no-op if the timer is not running. If the logger /// is disabled then no time is logged. void stop(); /// Start recording time on a stopped timer. /// /// This is a no-op if the timer is already running or if the logger is /// disabled. void start(); private: LogDomain& mLogger; bool mTimerRunning; mtbb::tick_count mRealTicks; // high precision }; /// This is a compile-time disabled logger. You are not supposed to dynamically /// call any non-const methods on it other than the constructor. Code that /// calls other code will compile but it is an error if any of those /// methods get called at runtime. template<> class LogDomain { public: static const bool compileTimeEnabled = false; LogDomain(const char* const, const char* const, const bool) {} bool enabled() const {return false;} bool streamEnabled() const {return false;} class Timer { public: Timer(LogDomain&) {} bool running() const {return false;} void stop() {MATHICGB_ASSERT(false);} void start() {MATHICGB_ASSERT(false);} }; Timer timer() { MATHICGB_ASSERT(false); return Timer(*this); } std::ostream& stream() { MATHICGB_ASSERT(false); abort(); //return *static_cast< std::ostream*>(0); } typedef unsigned long long Counter; Counter count() const {return 0;} void setCount(const Counter counter) {MATHICGB_ASSERT(false);} bool hasCount() const {return false;} void reset() {} }; namespace LogDomainInternal { // Helpers for the logging macroes template struct SelectValue {static const bool value = Default;}; template struct Tag_ {}; template struct Tag_0 {}; template struct Tag_1 {}; template struct SelectValue, Default> {static const bool value = false;}; template struct SelectValue, Default> {static const bool value = true;}; template struct LambdaRunner {L& log;}; template LambdaRunner lambdaRunner(L& l) { LambdaRunner r = {l}; return r; } template void operator+(LambdaRunner runner, T&& lambda) { lambda(runner.log, runner.log.stream()); } struct LogAliasRegisterer { LogAliasRegisterer(const char* alias, const char* of); }; } MATHICGB_NAMESPACE_END /// Defines LogDomainInternal::value_##NAME to be equal to the value of /// the macro MATHICGB_LOG_##NAME if that macro expands to 0 or 1. Otherwise /// the macro MATHICGB_LOG_##NAME is ignored and instead DEFAULT_VALUE is used. #define MATHICGB_CAPTURE_LOG_ENABLED(NAME, DEFAULT_VALUE) \ namespace mgb{namespace LogDomainInternal { \ template struct Tag_MATHICGB_LOG_##NAME {}; \ typedef MATHICGB_CONCATENATE_AFTER_EXPANSION(Tag_, MATHICGB_LOG_##NAME) \ SelectedTag_##NAME; \ static const bool value_##NAME = \ SelectValue::value; \ }} /// Defines a LogDomain with the given name and description. /// /// The logger is default compile-time enabled depending on MATHICGB_LOG_##NAME /// (see MATHICGB_CAPTURE_LOG_ENABLED) and it is initially runtime /// enabled depending on the value of DEFAULT_RUNTIME_ENABLED. It is default /// runtime enabled for streaming (when also enabled in general) depending on /// DEFAULT_RUNTIME_STREAM_ENABLED. #define MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS( \ NAME, DESCRIPTION, \ DEFAULT_RUNTIME_ENABLED, \ DEFAULT_RUNTIME_STREAM_ENABLED, \ DEFAULT_COMPILE_TIME_ENABLED \ ) \ MATHICGB_CAPTURE_LOG_ENABLED(NAME, DEFAULT_COMPILE_TIME_ENABLED); \ namespace mgb{namespace logs { \ typedef LogDomain< ::mgb::LogDomainInternal::value_##NAME> Type##NAME; \ Type##NAME NAME( \ #NAME, \ DESCRIPTION, \ DEFAULT_RUNTIME_ENABLED, \ DEFAULT_RUNTIME_STREAM_ENABLED \ ); \ }} /// Defines a LogDomain with the given name and description. /// /// The defaults for the logger are as follows. /// compile-time: enabled, /// runtime: disabled, /// runtime streaming: enabled (only takes effect if also enabled) #define MATHICGB_DEFINE_LOG_DOMAIN(NAME, DESCRIPTION) \ MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS(NAME, DESCRIPTION, 0, 1, 1); #define MATHICGB_DEFINE_LOG_ALIAS(ALIAS, OF) \ namespace mgb{namespace LogDomainInternal { \ LogAliasRegisterer MATHICGB_CONCATENATE_AFTER_EXPANSION(reg_, __LINE__) \ (ALIAS, OF); \ }} /// This expression yields an l-value reference to the indicated logger. /// /// Example: /// auto timer = MATHICGB_LOGGER(MyDomain).timer(); #define MATHICGB_LOGGER(DOMAIN) ::mgb::logs::DOMAIN /// This expression yields the type of the indicated logger. /// /// Example: /// if (MATHICGB_LOGGER_TYPE(MyDomain)::compileTimeEnabled) /// std::ostream << "MyDomain is compiled time enabled"; #define MATHICGB_LOGGER_TYPE(DOMAIN) ::mgb::logs::Type##DOMAIN /// Runs the code in the following scope delimited by braces {} if the /// indicated logger is enabled for streaming - otherwise does /// nothing. Within the following scope there is a local reference /// variable log that refers to the indicated logger and a local /// reference variable stream that refers to log.stream(). /// /// Example: /// MATHICGB_IF_STREAM_LOG(MyDomain) { /// std::string msg; /// expensiveFunction(msg); /// stream << msg; // or log.stream() << msg; /// } #define MATHICGB_IF_STREAM_LOG(DOMAIN) \ if (MATHICGB_LOGGER(DOMAIN).streamEnabled()) \ LogDomainInternal::lambdaRunner(MATHICGB_LOGGER(DOMAIN)) + \ [&](MATHICGB_LOGGER_TYPE(DOMAIN)& log, std::ostream& stream) /// Display information to the log using <<. /// If domain is not enabled and stream enabled then the log message is not /// displayed and the code after << is not executed. /// /// Example: (f() only called if logger is enabled) /// MATHICGB_LOG(domain) << "f() = " << f(); #define MATHICGB_LOG(DOMAIN) \ if (MATHICGB_LOGGER(DOMAIN).streamEnabled()) MATHICGB_LOGGER(DOMAIN).stream() /// Will log the time to execute the remaining code in the current scope /// to the indicated domain. Also supports printing a message using <<. /// The message is printed right away while the time is printed when /// the scope ends. /// /// Example: /// MATHICGB_LOG_SCOPE_TIME(MyDomain) << "Starting timed task"; #define MATHICGB_LOG_TIME(DOMAIN) \ auto MATHICGB_CONCATENATE_AFTER_EXPANSION( \ DOMAIN, MATHICGB_CONCATENATE_AFTER_EXPANSION(_timer_, __LINE__)) \ (MATHICGB_LOGGER(DOMAIN).timer()); \ MATHICGB_LOG(DOMAIN) /// Increments the count of DOMAIN by the value of the expression BY. The /// expression BY is evaluated at most once and it is not evaluated if /// DOMAIN is disabled. /// /// Example: /// MATHICGB_LOG_INCREMENT_BY(MyDomain, 3); #define MATHICGB_LOG_INCREMENT_BY(DOMAIN, BY) \ do { \ auto& MGBLOG_log = MATHICGB_LOGGER(DOMAIN); \ if (MGBLOG_log.enabled()) { \ MGBLOG_log.setCount(MGBLOG_log.count() + BY); \ } \ } while (false) /// Increments the count of DOMAIN by 1. #define MATHICGB_LOG_INCREMENT(DOMAIN) \ MATHICGB_LOG_INCREMENT_BY(DOMAIN, 1) #endif mathicgb-master/src/mathicgb/LogDomainSet.cpp000077500000000000000000000134111311555162500215320ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "LogDomainSet.hpp" #include MATHICGB_NAMESPACE_BEGIN LogDomainSet::LogDomainSet(): mStartTime(mgb::mtbb::tick_count::now()) { } void LogDomainSet::registerLogDomain(LogDomain& domain) { MATHICGB_ASSERT(std::strcmp(domain.name(), "none") != 0); MATHICGB_ASSERT(std::strcmp(domain.name(), "all") != 0); mLogDomains.push_back(&domain); } LogDomain* LogDomainSet::logDomain(const char* const name) { const auto func = [&](const LogDomain* const ld){ return std::strcmp(ld->name(), name) == 0; }; const auto it = std::find_if(mLogDomains.begin(), mLogDomains.end(), func); return it == mLogDomains.end() ? static_cast*>(0) : *it; } const char* LogDomainSet::alias(const char* name) { const auto func = [&](const std::pair p){ return std::strcmp(p.first, name) == 0; }; const auto it = std::find_if(mAliases.begin(), mAliases.end(), func); return it == mAliases.end() ? static_cast(0) : it->second; } void LogDomainSet::registerLogAlias(const char* alias, const char* of) { MATHICGB_ASSERT(this->alias(alias) == 0); mAliases.push_back(std::make_pair(alias, of)); } void LogDomainSet::performLogCommandsInternal( const char prefix, const std::string& cmds, const char suffix ) { size_t offset = 0; while (offset < cmds.size()) { const size_t next = cmds.find(',', offset); performLogCommandInternal (prefix, cmds.substr(offset, next - offset), suffix); offset = next; if (offset < cmds.size()) { MATHICGB_ASSERT(cmds[offset] == ','); ++offset; } } } void LogDomainSet::performLogCommandInternal( char prefix, std::string cmd, char suffix ) { const auto isSign = [](const char c) {return c == '+' || c == '-' || c == '0';}; MATHICGB_ASSERT(prefix == ' ' || isSign(prefix)); MATHICGB_ASSERT(suffix == ' ' || isSign(suffix)); if (cmd.empty()) return; // This could be more efficient, but this is not supposed to be a // method that is called very often. if (isSign(cmd[0])) { if (prefix == ' ') prefix = cmd[0]; cmd.erase(cmd.begin()); } if (!cmd.empty() && isSign(*cmd.rbegin())) { if (suffix == ' ') suffix = *cmd.rbegin(); cmd.erase(cmd.end() - 1); } if (cmd == "none") return; if (cmd == "all") { for (auto it = mLogDomains.begin(); it != mLogDomains.end(); ++it) performLogCommandInternal(prefix, (*it)->name(), suffix); return; } auto aliasOf = alias(cmd.c_str()); if (aliasOf != 0) { performLogCommandsInternal(prefix, aliasOf, suffix); return; } // The default modifiers are +X0. if (prefix == ' ') prefix = '+'; if (suffix == ' ') suffix = '0'; auto log = logDomain(cmd.c_str()); if (log != 0) { if (prefix != '0') log->setEnabled(prefix != '-'); if (suffix != '0') log->setStreamEnabled(suffix == '+'); return; } mathic::reportError("Unknown log \"" + cmd + "\".\n"); } void LogDomainSet::printReport(std::ostream& out) const { printCountReport(out); printTimeReport(out); } void LogDomainSet::printCountReport(std::ostream& out) const { mathic::ColumnPrinter pr; auto& names = pr.addColumn(true); auto& counts = pr.addColumn(false); names << "Log name \n"; counts << " Count\n"; pr.repeatToEndOfLine('-'); bool somethingToReport = false; const auto end = logDomains().cend(); for (auto it = logDomains().cbegin(); it != end; ++it) { const auto& log = **it; if (!log.enabled() || !log.hasCount()) continue; somethingToReport = true; names << log.name() << " \n"; counts << " " << mathic::ColumnPrinter::commafy(log.count()) << '\n'; } if (!somethingToReport) return; out << "***** Logging count report *****\n\n" << pr << '\n'; } void LogDomainSet::printTimeReport(std::ostream& out) const { const auto allTime = (mgb::mtbb::tick_count::now() - mStartTime).seconds(); mathic::ColumnPrinter pr; auto& names = pr.addColumn(true); auto& times = pr.addColumn(false); auto& ratios = pr.addColumn(false); times.precision(3); times << std::fixed; ratios.precision(3); ratios << std::fixed; names << "Log name \n"; times << " Time/s (real)\n"; ratios << " Ratio\n"; pr.repeatToEndOfLine('-'); double timeSum = 0; bool somethingToReport = false; const auto end = logDomains().cend(); for (auto it = logDomains().cbegin(); it != end; ++it) { const auto& log = **it; if (!log.enabled() || !log.hasTime()) continue; somethingToReport = true; const auto logTime = log.loggedSecondsReal(); timeSum += logTime; names << log.name() << " \n"; times << logTime << '\n'; ratios << mathic::ColumnPrinter::percentDouble(logTime, allTime) << '\n'; } if (!somethingToReport) return; pr.repeatToEndOfLine('-'); names << "sum\n"; times << timeSum; ratios << mathic::ColumnPrinter::percentDouble(timeSum, allTime) << '\n'; const auto oldFlags = out.flags(); const auto oldPrecision = out.precision(); out << std::fixed; out.precision(3); out << "***** Logging time report *****\nTime elapsed: " << allTime << "s\n\n" << pr << '\n'; // todo: restore the stream state using RAII, since the above code might // throw an exception. out.precision(oldPrecision); out.flags(oldFlags); } void LogDomainSet::reset() { mStartTime = mgb::mtbb::tick_count::now(); const auto end = logDomains().cend(); for (auto it = logDomains().cbegin(); it != end; ++it) { MATHICGB_ASSERT(*it != 0); (*it)->reset(); } } LogDomainSet& LogDomainSet::singleton() { static LogDomainSet set; return set; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/LogDomainSet.hpp000077500000000000000000000060611311555162500215420ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_LOG_DOMAIN_SET_GUARD #define MATHICGB_LOG_DOMAIN_SET_GUARD #include "LogDomain.hpp" #include "mtbb.hpp" #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN class LogDomainSet { public: void registerLogDomain(LogDomain& domain); void registerLogDomain(const LogDomain& domain) {} void registerLogAlias(const char* alias, const char* of); /// A log command has the format AXB, where /// X the name of a compile-time enabled log domain /// A a prefix /// B a suffix /// The possible values of A are /// enable X (this is the empty string) /// + enable X /// - disable X /// 0 do nothing /// The possible values of B are /// do nothing (this is the empty string) /// + stream-enabled X /// - stream-disable X /// 0 do nothing /// /// No white-space is allowed. /// If the command cannot be parsed then you will get an exception. /// /// *** Example *** /// Consider this sequence of commands: /// "+MyLog-" will enabled MyLog, but silence any streaming from it. /// "+MyLog" will make no difference, as MyLog is already enabled. /// "-MyLog+" will disable MyLog, but set the streaming state to enabled. /// As MyLog is disabled there will still be no streaming output. /// "+MyLog" will enabled MyLog. Since the streaming state was enabled /// before, we now get streaming. /// void performLogCommand(std::string cmd) {performLogCommandInternal(' ', std::move(cmd), ' ');} /// Performs a comma-seperated list of commands. No white-space is allowed. void performLogCommands(const std::string& cmds) {performLogCommandsInternal(' ', cmds, ' ');} LogDomain* logDomain(const char* const name); const char* alias(const char* name); const std::vector*>& logDomains() const {return mLogDomains;} const std::vector>& aliases() const {return mAliases;} void printReport(std::ostream& out) const; void printTimeReport(std::ostream& out) const; void printCountReport(std::ostream& out) const; /// Resets the logging system as though the program had just started up. /// This resets all counts, all recorded time and the enabledness of all logs. /// You should not have a timer running for a log when you call this method. void reset(); static LogDomainSet& singleton(); private: void performLogCommandInternal( char prefix, std::string name, char suffix ); void performLogCommandsInternal( const char prefix, const std::string& cmds, const char suffix ); LogDomainSet(); // private for singleton std::vector*> mLogDomains; std::vector> mAliases; mgb::mtbb::tick_count mStartTime; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/MathicIO.hpp000077500000000000000000000376261311555162500206650ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MATHIC_IO_GUARD #define MATHICGB_MATHIC_IO_GUARD #include "Basis.hpp" #include "Poly.hpp" #include "Scanner.hpp" #include "PolyRing.hpp" #include "MonoProcessor.hpp" #include #include MATHICGB_NAMESPACE_BEGIN /// Class for input and output in Mathic's format. template< class Monoid = PolyRing::Monoid, class BaseField = PolyRing::Field > class MathicIO; template class MathicIO { public: typedef BF BaseField; typedef typename BaseField::Element Coefficient; typedef typename BaseField::RawElement RawCoefficient; typedef M Monoid; typedef typename Monoid::MonoRef MonoRef; typedef typename Monoid::Exponent Exponent; typedef typename Monoid::VarIndex VarIndex; typedef typename Monoid::ConstMonoRef ConstMonoRef; typedef typename Monoid::Order Order; typedef typename Monoid::MonoVector MonoVector; typedef MonoProcessor Processor; typedef typename Order::Gradings Gradings; BaseField readBaseField(Scanner& in); void writeBaseField(const BaseField& field, std::ostream& out); std::pair, Processor> readRing( const bool withComponent, Scanner& in ); void writeRing( const PolyRing& ring, const Processor& processor, const bool withComponent, std::ostream& out ); Order readOrderWithVarCount(bool withComponent, Scanner& in); void writeOrderWithVarCount (const Order& monoid, const bool withComponent, std::ostream& out); Order readOrder( const VarIndex varCount, const bool withComponent, Scanner& in ); void writeOrder( const Order& order, const bool withComponent, std::ostream& out ); Basis readBasis( const PolyRing& ring, const bool readComponent, Scanner& in ); void writeBasis( const Basis& basis, const bool writeComponent, std::ostream& out ); /// Reads a polynomial and does not reorder the terms to be in descending /// order. Poly readPolyDoNotOrder( const PolyRing& ring, const bool readComponent, Scanner& in ); /// Reads a polynomial and orders the terms in descending order. Poly readPoly(const PolyRing& ring, const bool readComponent, Scanner& in); void writePoly( const Poly& poly, const bool writeComponent, std::ostream& out ); void readTerm( const PolyRing& ring, const bool readComponent, Coefficient& coef, MonoRef mono, Scanner& in ); void writeTerm( const PolyRing& ring, const bool writeComponent, const Coefficient coef, ConstMonoRef mono, bool writeSignEvenIfPositive, std::ostream& out ); /// Read a monomial with no coefficient. A 1 on its own is not /// considered a coefficient here - it is the monomial with all /// exponents zero and no coefficient. /// /// @todo: Eventually, pick up readComponent from Monoid::HasComponent. void readMonomial( const Monoid& monoid, const bool readComponent, MonoRef mono, Scanner& in ); /// Print a monomial with no coefficient. void writeMonomial( const Monoid& monoid, const bool writeComponent, ConstMonoRef mono, std::ostream& out ); /// Reads a non-empty space-separated list of monomials. The monomials /// are appended to the end of the vector. void readMonomialVector( const bool readComponents, Scanner& in, MonoVector& v ) { MATHICGB_ASSERT(Monoid::HasComponent || !readComponents); while (true) { v.push_back(); readMonomial(v.monoid(), readComponents, v.back(), in); if (in.peek() != ' ') break; in.get(); } } void writeMonomialVector( const MonoVector& v, const bool writeComponent, std::ostream& out ) { MATHICGB_ASSERT(Monoid::HasComponent || !writeComponent); for (auto it = v.begin(); it != v.end(); ++it) { if (it != v.begin()) out << ' '; writeMonomial(v.monoid(), writeComponent, *it, out); } out << '\n'; } /// Read the trailing indicator of the component of a module monomial. void readComponent( const Monoid& monoid, MonoRef mono, Scanner& in ); void writeComponent( const Monoid& monoid, ConstMonoRef mono, std::ostream& out ); }; template auto MathicIO::readBaseField(Scanner& in) -> BaseField { return BaseField(in.readInteger()); } template void MathicIO::writeBaseField( const BaseField& field, std::ostream& out ) { out << field.charac(); } template auto MathicIO::readRing( const bool withComponent, Scanner& in ) -> std::pair, Processor> { auto baseField = readBaseField(in); const auto varCount = in.readInteger(); auto order = readOrder(varCount, withComponent, in); const bool componentsAscendingDesired = order.componentsAscendingDesired(); const bool schreyering = order.schreyering(); auto ring = make_unique (std::move(baseField), Monoid(std::move(order))); Processor processor( ring->monoid(), componentsAscendingDesired, schreyering ); return std::make_pair(std::move(ring), std::move(processor)); } template void MathicIO::writeRing( const PolyRing& ring, const Processor& processor, const bool withComponent, std::ostream& out ){ writeBaseField(ring.field(), out); out << ' ' << ring.varCount() << '\n'; auto&& order = ring.monoid().makeOrder( processor.componentsAscendingDesired(), processor.schreyering() ); writeOrder(order, withComponent, out); } template auto MathicIO::readOrderWithVarCount(bool withComponent, Scanner& in) -> Order { const auto varCount = in.readInteger(); return readOrder(varCount, withComponent, in); } template void MathicIO::writeOrderWithVarCount( const Order& order, const bool withComponent, std::ostream& out ) { out << order.varCount() << '\n'; writeOrder(order, withComponent, out); } template auto MathicIO::readOrder( const VarIndex varCount, const bool withComponent, Scanner& in ) -> Order { const bool schreyering = in.match("schreyer"); bool lexBaseOrder = !in.match("revlex") && in.match("lex"); auto gradingCount = in.readInteger(); bool componentsAscendingDesired = true; auto componentCompareIndex = Order::ComponentAfterBaseOrder; Gradings gradings; gradings.reserve(static_cast(varCount) * gradingCount); for (VarIndex grading = 0; grading < gradingCount; ++grading) { const bool com = in.match("component"); if (com || in.match("revcomponent")) { if (!withComponent) in.reportError("Cannot specify component comparison for non-modules."); MATHICGB_ASSERT(Monoid::HasComponent); if (componentCompareIndex != Order::ComponentAfterBaseOrder) in.reportError("Component comparison must be specified at most once."); componentsAscendingDesired = com; componentCompareIndex = grading; } else { for (VarIndex i = 0; i < varCount; ++i) gradings.emplace_back(in.readInteger()); } } const bool moreLex = in.match("_lex"); if (moreLex || in.match("_revlex")) { lexBaseOrder = moreLex; const bool moreCom = in.match("component"); if (moreCom || in.match("revcomponent")) { if (!withComponent) in.reportError("Cannot specify component comparison for non-modules."); MATHICGB_ASSERT(Monoid::HasComponent); componentsAscendingDesired = moreCom; } } Order order( varCount, std::move(gradings), lexBaseOrder ? Order::LexBaseOrderFromRight : Order::RevLexBaseOrderFromRight, componentCompareIndex, componentsAscendingDesired, schreyering ); return std::move(order); } template void MathicIO::writeOrder( const Order& order, const bool withComponent, std::ostream& out ) { MATHICGB_ASSERT(Monoid::HasComponent || !withComponent); const auto baseOrder = order.baseOrder() == Order::LexBaseOrderFromRight ? "lex" : "revlex"; const auto componentOrder = order.componentsAscendingDesired() ? "component" : "revcomponent"; if (order.schreyering()) out << "schreyer "; const bool componentLast = order.componentBefore() == Order::ComponentAfterBaseOrder; out << baseOrder << ' ' << order.gradingCount() + !componentLast << '\n'; for (VarIndex grading = 0; grading < order.gradingCount(); ++grading) { if (withComponent && grading == order.componentBefore()) out << ' ' << componentOrder << '\n'; for (VarIndex var = 0; var < order.varCount(); ++var) { const auto index = var + grading * order.varCount(); out << ' ' << unchar(order.gradings()[index]); } out << '\n'; } if (withComponent && order.componentBefore() == order.gradingCount()) out << ' ' << componentOrder << '\n'; if ( withComponent && !order.componentsAscendingDesired() && order.componentBefore() == Order::ComponentAfterBaseOrder ) { out << " _" << baseOrder << "\n " << componentOrder << '\n'; } } template Basis MathicIO::readBasis( const PolyRing& ring, const bool readComponent, Scanner& in ) { const auto polyCount = in.readInteger(); Basis basis(ring); for (size_t i = 0; i < polyCount; ++i) { auto p = make_unique(readPoly(ring, readComponent, in)); *p = p->polyWithTermsDescending(); basis.insert(std::move(p)); } return std::move(basis); } template void MathicIO::writeBasis( const Basis& basis, const bool writeComponent, std::ostream& out ) { out << basis.size() << '\n'; for (size_t i = 0; i < basis.size(); ++i) { out << ' '; writePoly(*basis.getPoly(i), writeComponent, out); out << '\n'; } } template Poly MathicIO::readPoly( const PolyRing& ring, const bool readComponent, Scanner& in ) { return readPolyDoNotOrder(ring, readComponent, in).polyWithTermsDescending(); } template Poly MathicIO::readPolyDoNotOrder( const PolyRing& ring, const bool readComponent, Scanner& in ) { Poly p(ring); // also skips whitespace if (in.match('0') || in.match("+0") || in.match("-0")) return std::move(p); MATHICGB_ASSERT(!in.peekWhite()); auto mono = ring.monoid().alloc(); auto coef = ring.field().zero(); do { if (!p.isZero() && !in.peekSign() && (!readComponent || in.peek() != '<')) in.expect('+', '-'); readTerm(ring, readComponent, coef, mono, in); p.append(coef.value(), *mono); } while (!in.peekWhite() && !in.matchEOF()); return std::move(p); } template void MathicIO::writePoly( const Poly& poly, const bool writeComponent, std::ostream& out ) { if (poly.isZero()) { out << '0'; return; } const auto end = poly.end(); for (auto it = poly.begin(); it != end; ++it) { writeTerm( poly.ring(), writeComponent, it.coef(), it.mono(), it != poly.begin(), out ); } } template void MathicIO::readTerm( const PolyRing& ring, const bool readComponent, Coefficient& coef, MonoRef mono, Scanner& in ) { // ** Read coefficient, if any. const auto& field = ring.field(); const auto& monoid = ring.monoid(); const bool negate = !in.match('+') && in.match('-'); if (in.peekDigit()) { coef = in.readModular(field, negate); if (!in.peekAlpha()) { // Identify a number c on its own as the monomial 1 times c. monoid.setIdentity(mono); if (readComponent) this->readComponent(monoid, mono, in); return; } } else if (negate) coef = field.minusOne(); else coef = field.one(); readMonomial(monoid, readComponent, mono, in); } template void MathicIO::writeTerm( const PolyRing& ring, const bool writeComponent, Coefficient coef, ConstMonoRef mono, bool writeSignEvenIfPositive, std::ostream& out ) { Coefficient coef1 = coef; if (ring.field().isNegative(coef)) { out << "-"; coef1 = ring.field().negativeNonZero(coef); } else if (writeSignEvenIfPositive) out << '+'; if (!ring.field().isOne(coef1)) { out << unchar(coef1.value()); if (ring.monoid().isIdentity(mono)) { if (writeComponent) this->writeComponent(ring.monoid(), mono, out); return; } } writeMonomial(ring.monoid(), writeComponent, mono, out); } template void MathicIO::readMonomial( const Monoid& monoid, const bool readComponent, MonoRef mono, Scanner& in ) { MATHICGB_ASSERT(!readComponent || Monoid::HasComponent); monoid.setIdentity(mono); if (in.peek() == '1') { const auto e = in.readInteger(); if (e != 1) { std::ostringstream err; err << "Expected monomial, but got " << e << " (did you mean 1?)."; in.reportError(err.str()); } } else if (!readComponent || in.peek() != '<') { bool sawSome = false; while (true) { const auto letterCount = 'z' - 'a' + 1; const auto letter = in.peek(); VarIndex var; if ('a' <= letter && letter <= 'z') var = letter - 'a'; else if ('A' <= letter && letter <= 'Z') var = (letter - 'A') + letterCount; else if (sawSome) break; else { std::ostringstream err; err << "Expected letter while reading monomial, but got '" << static_cast(letter) << "'."; in.reportError(err.str()); return; } in.get(); // skip past letter MATHICGB_ASSERT(var < 2 * letterCount); if (var >= monoid.varCount()) { std::ostringstream err; err << "Saw the variable " << static_cast(letter) << ", but the monoid only has " << monoid.varCount() << " variables."; in.reportError(err.str()); return; } if (monoid.externalExponent(mono, var) > static_cast(0)) { std::ostringstream err; err << "Variable " << static_cast(letter) << " must not be written twice in one monomial."; in.reportError(err.str()); } if (in.peekDigit()) monoid.setExternalExponent(var, in.readInteger(), mono); else monoid.setExternalExponent(var, static_cast(1), mono); sawSome = true; } } if (readComponent) this->readComponent(monoid, mono, in); } template void MathicIO::readComponent( const Monoid& monoid, MonoRef mono, Scanner& in ) { MATHICGB_ASSERT(Monoid::HasComponent); in.expect('<'); monoid.setComponent(in.readInteger(), mono); in.expect('>'); } template void MathicIO::writeComponent( const Monoid& monoid, ConstMonoRef mono, std::ostream& out ) { MATHICGB_ASSERT(Monoid::HasComponent); out << '<' << unchar(monoid.component(mono)) << '>'; } /// Print a monomial with no coefficient. template void MathicIO::writeMonomial( const Monoid& monoid, const bool writeComponent, ConstMonoRef mono, std::ostream& out ) { const auto letterCount = 'z' - 'a' + 1; bool printedSome = false; for (VarIndex var = 0; var < monoid.varCount(); ++var) { const auto e = monoid.exponent(mono, var); if (e == 0) continue; char letter; if (var < letterCount) letter = 'a' + static_cast(var); else if (var < 2 * letterCount) letter = 'A' + (static_cast(var) - letterCount); else { mathic::reportError("Too few letters in alphabet to print variable."); return; } printedSome = true; out << letter; if (e != 1) out << unchar(e); } if (!printedSome) out << '1'; if (writeComponent) this->writeComponent(monoid, mono, out); } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ModuleMonoSet.cpp000077500000000000000000000114351311555162500217430ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ModuleMonoSet.hpp" #include "StaticMonoMap.hpp" #include "MathicIO.hpp" MATHICGB_NAMESPACE_BEGIN template< bool UseKDTree, bool AllowRemovals, bool UseDivMask > class ConcreteModuleMonoSet : public ModuleMonoSet { public: typedef PolyRing::Monoid Monoid; struct NoData {}; typedef StaticMonoLookup Lookup; typedef typename Lookup::Entry Entry; ConcreteModuleMonoSet(const Monoid& monoid, const size_t componentCount): mMonoid(monoid), mComponentCount(componentCount), mLookups(reinterpret_cast( new char[sizeof(Lookup) * componentCount] )) { for (size_t component = 0; component < componentCount; ++component) new (&mLookups[component]) Lookup(monoid); } virtual ~ConcreteModuleMonoSet() { delete[] reinterpret_cast(mLookups); } virtual bool insert(ConstMonoRef m) { const auto c = monoid().component(m); MATHICGB_ASSERT(c < componentCount()); if (member(m)) return false; if (AllowRemovals) mLookups[c].removeMultiples(m); mLookups[c].insert(m, NoData()); return true; } virtual bool member(ConstMonoRef m) { const auto c = monoid().component(m); MATHICGB_ASSERT(c < componentCount()); return mLookups[c].divisor(m) != 0; } virtual std::string name() const { return Lookup(monoid()).getName(); } virtual void display(std::ostream& out) const { std::vector monomials; for (size_t c = 0; c < componentCount(); ++c) { const Lookup& lookup = mLookups[c]; if (lookup.size() == 0) continue; out << " " << c << ": "; monomials.clear(); lookup.forAll([&](const Entry& entry) { monomials.emplace_back(entry.mono().ptr()); }); const auto& monoid = this->monoid(); // workaround for gcc 4.5.3 issue const auto cmp = [&](ConstMonoPtr a, ConstMonoPtr b) { return monoid.lessThan(*a, *b); }; std::sort(monomials.begin(), monomials.end(), cmp); for (auto mono = monomials.cbegin(); mono != monomials.cend(); ++mono) { MathicIO<>().writeMonomial(monoid, false, **mono, out); out << " "; } out << '\n'; } } virtual void getMonomials(std::vector& monomials) const { for (size_t c = 0; c < componentCount(); ++c) { mLookups[c].forAll( [&](const Entry& entry) { monomials.push_back(entry.mono().ptr()); } ); } } virtual void forAllVirtual(EntryOutput& consumer) { for (size_t c = 0; c < componentCount(); ++c) { mLookups[c].forAll( [&](const Entry& entry) { consumer.proceed(entry.mono()); } ); } } virtual size_t elementCount() const { size_t count = 0; for (size_t c = 0; c < componentCount(); ++c) count += mLookups[c].size(); return count; } virtual size_t getMemoryUse() const { size_t count = 0; for (size_t c = 0; c < componentCount(); ++c) count += mLookups[c].getMemoryUse(); return count; } const Monoid& monoid() const {return mMonoid;} size_t componentCount() const {return mComponentCount;} private: const Monoid& mMonoid; // We cannot use std::vector as Lookup might not be copyable or movable. const size_t mComponentCount; Lookup* const mLookups; }; ModuleMonoSet::~ModuleMonoSet() {} void ModuleMonoSet::displayCodes(std::ostream& out) { out << " 1 list, using divmasks\n" " 2 KD-tree, using divmasks\n" " 3 list\n" " 4 KD-tree\n"; } namespace { class ModuleMonoSetFactory { public: typedef PolyRing::Monoid Monoid; std::unique_ptr make( const Monoid& monoid, int type, size_t componentCount, bool allowRemovals ) { const Params params = {monoid, type, componentCount}; return staticMonoLookupMake > (type, allowRemovals, params); } private: struct Params { const Monoid& monoid; int type; size_t componentCount; }; template struct Make { static std::unique_ptr make(const Params& params) { return make_unique > (params.monoid, params.componentCount); } }; }; } std::unique_ptr ModuleMonoSet::make( const Monoid& monoid, const int type, const size_t components, const bool allowRemovals ) { return ModuleMonoSetFactory().make(monoid, type, components, allowRemovals); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ModuleMonoSet.hpp000077500000000000000000000047561311555162500217600ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MODULE_MONO_SET_GUARD #define MATHICGB_MODULE_MONO_SET_GUARD #include "PolyRing.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN /// Represents the ideal generated by a set of module monomials. class ModuleMonoSet { public: typedef PolyRing::Monoid Monoid; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::ConstMonoPtr ConstMonoPtr; virtual ~ModuleMonoSet(); /// Inserts mono into this set if it is not already a member of the /// ideal generated by this set. Returns true if mono was inserted. /// If this set was constructed to allow removals, any other module /// monomials divisible by mono will be removed. A reference to /// mono is retained but ownership is not passed. virtual bool insert(ConstMonoRef mono) = 0; /// Returns true if mono is a member of the ideal generated by this set. virtual bool member(ConstMonoRef mono) = 0; /// Prints a human-readable representation of this set to out. virtual void display(std::ostream& out) const = 0; /// Returns the number of module monomials in this set. Take care not to /// confuse this with the number of components. virtual size_t elementCount() const = 0; class EntryOutput { public: virtual void proceed(ConstMonoRef mono) = 0; }; /// Calls consumer.proceed(mono) for each mono in this set. virtual void forAllVirtual(EntryOutput& consumer) = 0; /// Calls func(mono) for eac mono in this set. template void forAll(Func&& func) { struct Wrap : EntryOutput { Wrap(Func&& func): mFunc(std::forward(func)) {} virtual void proceed(ConstMonoRef mono) {mFunc(mono);} Func&& mFunc; } wrap(std::forward(func)); forAllVirtual(wrap); } /// Returns a descriptive name for the implementation of this set. virtual std::string name() const = 0; virtual size_t getMemoryUse() const = 0; /// Prints a human-readable description of the type codes for the /// implementations of this interface. static void displayCodes(std::ostream& out); /// This is how you should instantiate classes that implement this interface. static std::unique_ptr make( const Monoid& monoid, int type, // the type code - which implementation do you want? size_t componentCount, bool allowRemovals ); }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/MonoArena.hpp000077500000000000000000000152501311555162500210740ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MONO_ARENA_GUARD #define MATHICGB_MONO_ARENA_GUARD #include "Range.hpp" #include #include MATHICGB_NAMESPACE_BEGIN /// Like a Monoid::MonoVector, except that references are not /// invalidated when additional memory must be allocated. /// /// Todo: Think of a better name. We can't deallocate at the end, so /// MonoArena is not really an Arena. template class MonoArena; template class MonoArena { public: typedef M Monoid; typedef typename Monoid::Mono Mono; typedef typename Monoid::MonoRef MonoRef; typedef typename Monoid::ConstMonoRef ConstMonoRef; typedef typename Monoid::MonoPtr MonoPtr; typedef typename Monoid::ConstMonoPtr ConstMonoPtr; typedef typename Monoid::MonoVector MonoVector; typedef Flatten::const_iterator> const_iterator; // *** Constructors and assignment MonoArena(const Monoid& monoid) { mVectors.emplace_back(monoid); } MonoArena(const MonoArena& a): mVectors(a.mVectors) {} MonoArena(MonoArena&& a): mVectors(std::move(a.mVectors)) {} MonoArena& operator=(const MonoArena& a) { MATHICGB_ASSERT(monoid() == a.monoid()); mVectors = a.mVectors; return *this; } MonoArena& operator=(MonoArena&& a) { MATHICGB_ASSERT(monoid() == a.monoid()); mVectors = std::move(a.mVectors); return *this; } // *** Iterators const_iterator begin() const { return makeFlatten(std::begin(mVectors), std::end(mVectors)); } const_iterator end() const { return makeFlatten(std::end(mVectors), std::end(mVectors)); } const_iterator cbegin() const {return begin();} const_iterator cend() const {return end();} // *** Size and capacity size_t size() const { auto count = size_t(0); for (const auto& v : mVectors) count += v.size(); return count; } bool empty() const { MATHICGB_ASSERT(!mVectors.empty()); return mVectors.front().empty(); } // *** Element access ConstMonoRef front() const { MATHICGB_ASSERT(!empty()); MATHICGB_ASSERT(!mVectors.front().empty()); return mVectors.front().front(); } MonoRef back() { MATHICGB_ASSERT(!empty()); MATHICGB_ASSERT(!backVector().empty()); return backVector().back(); } ConstMonoRef back() const { MATHICGB_ASSERT(!empty()); MATHICGB_ASSERT(!backVector().empty()); return backVector().back(); } // *** Modifiers /// Appends the identity. void push_back() { MATHICGB_ASSERT(debugAssertValid()); ensureSpace(); return; backVector().push_back(); MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(monoid().isIdentity(back())); } void push_back(ConstMonoRef mono) { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(monoid().debugValid(mono)); ensureSpace(); backVector().push_back(mono); MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(monoid().equal(back(), mono)); } template void push_back( const Monoid& monoidMono, typename Monoid::ConstMonoRef mono ) { MATHICGB_ASSERT(monoidMono.debugValid(mono)); MATHICGB_ASSERT(debugAssertValid()); ensureSpace(); backVector().push_back(monoidMono, mono); MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(monoid().equal(monoidMono, mono, back())); } void swap(MonoArena& a) { MATHICGB_ASSERT(monoid() == a.monoid()); MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(a.debugAssertValid()); mVectors.swap(a.mVectors); MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(a.debugAssertValid()); } void clear() { MATHICGB_ASSERT(debugAssertValid()); auto last = std::end(mVectors); --last; last->clear(); mVectors.erase(mVectors.begin(), last); MATHICGB_ASSERT(debugAssertValid()); } // *** Other size_t memoryBytesUsed() const { auto sum = size_t(0); for (const auto& v : mVectors) sum += v.memoryBytesUsed(); return sum; } const Monoid& monoid() const {return mVectors.back().monoid();} bool debugAssertValid() const { #ifdef MATHICGB_DEBUG MATHICGB_ASSERT(!mVectors.empty()); for (const auto& p : adjPairRange(mVectors)) { MATHICGB_ASSERT(p.first.monoid() == p.second.monoid()); MATHICGB_ASSERT(p.first.capacity() <= p.second.capacity()); } #endif return true; } private: /// Ensures that there is space for at least one more monomial. /// /// @todo: if monomials ever become variable-size, then this might /// allocate far more than double the memory of the previous /// vector. The problem is that they might actually take up, say, 128 bytes /// but the worst case is 1024k. Then if 1000 monomials fit in the previous /// vector, the next vector will allocate 2 * 1000 * 1024k bytes, which /// is far more than double what the previous vector did. Make it actually /// double the bytes. void ensureSpace() { MATHICGB_ASSERT(debugAssertValid()); if (!backVector().atCapacity()) return; const auto oldSize = backVector().size(); if (oldSize > std::numeric_limits::max() / 2) throw std::bad_alloc(); const auto newSize = 2 * oldSize; mVectors.emplace_back(monoid()); backVector().reserve(newSize); MATHICGB_ASSERT(debugAssertValid()); } MonoVector& backVector() { MATHICGB_ASSERT(!mVectors.empty()); return mVectors.back(); } const MonoVector& backVector() const { MATHICGB_ASSERT(!mVectors.empty()); return mVectors.back(); } std::vector mVectors; }; /// Returns true if a and b contain the same monomials in the same order. template bool operator==(const MonoArena& a, const MonoArena& b) { MATHICGB_ASSERT(a.monoid() == b.monoid()); MATHICGB_ASSERT(a.debugAssertValid()); MATHICGB_ASSERT(b.debugAssertValid()); typedef typename Monoid::ConstMonoRef ConstMonoRef; const auto& monoid = a.monoid(); auto cmpEqual = [&monoid](ConstMonoRef monoA, ConstMonoRef monoB) { return monoid.equal(monoA, monoB); }; return std::equal(std::begin(a), std::end(a), std::begin(b), cmpEqual); } /// As !(*this == v). template bool operator!=(const MonoArena& a, const MonoArena& b) { MATHICGB_ASSERT(a.monoid() == b.monoid()); return !(a == b); } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/MonoLookup.cpp000077500000000000000000000117001311555162500213060ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "MonoLookup.hpp" #include "SigPolyBasis.hpp" #include "StaticMonoMap.hpp" #include MATHICGB_NAMESPACE_BEGIN namespace { template< bool UseKDTree, bool AllowRemovals, bool UseDivMask > class ConcreteMonoLookup : public MonoLookup { public: ConcreteMonoLookup( const Monoid& monoid, int type, bool preferSparseReducers ): mLookup(monoid), mType(type), mPreferSparseReducers(preferSparseReducers), mBasis(0), mSigBasis(0) {} const Monoid& monoid() const {return mLookup.monoid();} bool preferSparseReducers() const {return mPreferSparseReducers;} // *** Virtual interface follows virtual void setBasis(const PolyBasis& basis) { if (mBasis == &basis) return; MATHICGB_ASSERT(mBasis == 0); MATHICGB_ASSERT(&monoid() == &basis.ring().monoid()); mBasis = &basis; } virtual void setSigBasis(const SigPolyBasis& sigBasis) { if (mSigBasis == &sigBasis) return; MATHICGB_ASSERT(mSigBasis == 0); MATHICGB_ASSERT(mBasis == 0 || mBasis == &sigBasis.basis()); MATHICGB_ASSERT(&monoid() == &sigBasis.basis().ring().monoid()); mSigBasis = &sigBasis; setBasis(sigBasis.basis()); } const SigPolyBasis& sigBasis() const { MATHICGB_ASSERT(mSigBasis != 0); return *mSigBasis; } const PolyBasis& basis() const { MATHICGB_ASSERT(mBasis != 0); return *mBasis; } virtual void insert(ConstMonoRef mono, size_t index) { mLookup.insert(mono, index); } virtual size_t regularReducer(ConstMonoRef sig, ConstMonoRef mono) const { return mLookup.regularReducer (sig, mono, sigBasis(), preferSparseReducers()); } virtual size_t classicReducer(ConstMonoRef mono) const { return mLookup.classicReducer(mono, basis(), preferSparseReducers()); } virtual std::string getName() const {return mLookup.getName();} virtual size_t getMemoryUse() const {return mLookup.getMemoryUse();} virtual size_t highBaseDivisor(size_t newGenerator) const { return mLookup.highBaseDivisor(newGenerator, sigBasis()); } virtual void lowBaseDivisors( std::vector& divisors, size_t maxDivisors, size_t newGenerator ) const { return mLookup.lowBaseDivisors (divisors, maxDivisors, newGenerator, sigBasis()); } virtual size_t minimalLeadInSig(ConstMonoRef sig) const { return mLookup.minimalLeadInSig(sig, sigBasis()); } virtual int type() const {return mType;} virtual void multiples(ConstMonoRef mono, EntryOutput& consumer) const { mLookup.multiples(mono, consumer); } virtual size_t divisor(ConstMonoRef mono) const { const auto entry = mLookup.divisor(mono); return entry == 0 ? size_t(-1) : entry->data(); } virtual void divisors(ConstMonoRef mono, EntryOutput& consumer) const { mLookup.divisors(mono, consumer); } virtual void removeMultiples(ConstMonoRef mono) { mLookup.removeMultiples(mono); } virtual void remove(ConstMonoRef mono) { return mLookup.remove(mono); } virtual size_t size() const {return mLookup.size();} private: StaticMonoLookup mLookup; const int mType; const bool mPreferSparseReducers; PolyBasis const* mBasis; SigPolyBasis const* mSigBasis; }; class ConcreteFactory : public MonoLookup::Factory { public: ConcreteFactory(const Monoid& monoid, int type): mMonoid(monoid), mType(type) {} virtual std::unique_ptr make( bool preferSparseReducers, bool allowRemovals ) const { Params params = {mMonoid, mType, preferSparseReducers}; return staticMonoLookupMake >(mType, allowRemovals, params); } private: struct Params { const Monoid& monoid; int type; bool preferSparseReducers; }; template struct Make { static std::unique_ptr make(const Params& params) { auto p = new ConcreteMonoLookup (params.monoid, params.type, params.preferSparseReducers); return std::unique_ptr(p); } }; const Monoid& mMonoid; const int mType; }; } MonoLookup::~MonoLookup() {} std::unique_ptr MonoLookup::makeFactory( const Monoid& monoid, const int type ) { return std::unique_ptr(new ConcreteFactory(monoid, type)); } void MonoLookup::displayCodes(std::ostream& out) { out << " 1 list, using divmasks\n" " 2 KD-tree, using divmasks\n" " 3 list\n" " 4 KD-tree\n"; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/MonoLookup.hpp000077500000000000000000000065601311555162500213230ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MONO_LOOKUP_GUARD #define MATHICGB_MONO_LOOKUP_GUARD #include "PolyRing.hpp" #include MATHICGB_NAMESPACE_BEGIN class PolyBasis; class SigPolyBasis; // Supports queries on the lead terms of the monomials in a PolyBasis. // todo: rename to MonomialLookup. class MonoLookup { public: typedef PolyRing::Monoid Monoid; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::ConstMonoPtr ConstMonoPtr; virtual ~MonoLookup(); // Call after construction. Can be called multiple times, but only if the // parameter object is the same each time. virtual void setBasis(const PolyBasis& basis) = 0; // Call after construction. Can be called multiple times, but only if the // parameter object is the same each time. virtual void setSigBasis(const SigPolyBasis& sigBasis) = 0; virtual void insert(ConstMonoRef mono, size_t index) = 0; // Returns the index of a basis element that regular reduces mono in // signature sig. Returns -1 if no such element exists. A basis element // u is a regular reducer if leadTerm(u) divides mono // and (mono / leadTerm(u)) * signature(u) < sig. virtual size_t regularReducer(ConstMonoRef sig, ConstMonoRef mono) const = 0; // Returns the index of a basis element whose lead term divides mono. The // strategy used to break ties is up to the implementation of the interface, // but the outcome must be deterministic. virtual size_t classicReducer(ConstMonoRef mono) const = 0; virtual std::string getName() const = 0; virtual size_t getMemoryUse() const = 0; virtual size_t highBaseDivisor(size_t newGenerator) const = 0; virtual void lowBaseDivisors( std::vector& divisors, size_t maxDivisors, size_t newGenerator ) const = 0; virtual size_t minimalLeadInSig(ConstMonoRef sig) const = 0; virtual int type() const = 0; /// Prints a human-readable description of the type codes for the /// implementations of this interface. static void displayCodes(std::ostream& out); class Factory { public: virtual std::unique_ptr make (bool preferSparseReducers, bool allowRemovals) const = 0; }; static std::unique_ptr makeFactory (const Monoid& monoid, int type); class EntryOutput { public: // Stop whatever is happening if proceed returns false. virtual bool proceed(size_t index) = 0; }; // Calls consumer.proceed(index) for each element whose lead term // divides mono. Stops the search if proceed returns false. virtual void multiples(ConstMonoRef mono, EntryOutput& consumer) const = 0; // Returns the index of a basis element whose lead term divides mono. virtual size_t divisor(ConstMonoRef mono) const = 0; // Calls consumer.proceed(index) for each element whose term // mono divides. Stops the search if proceed returns false. virtual void divisors(ConstMonoRef mono, EntryOutput& consumer) const = 0; // Removes multiples of mono. An element equal to mono counts as a multiple. virtual void removeMultiples(ConstMonoRef mono) = 0; // Removes entries whose monomial are equal to mono. virtual void remove(ConstMonoRef mono) = 0; // Returns how many elements are in the data structure. virtual size_t size() const = 0; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/MonoMonoid.hpp000077500000000000000000001767131311555162500213070ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MONO_MONOID_GUARD #define MATHICGB_MONO_MONOID_GUARD #include "MonoOrder.hpp" #include "NonCopyable.hpp" #include #include #include #include #include #include #include #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// Implements the monoid of (monic) monomials with integer /// non-negative exponents. Exponent must be an unsigned integer type that is /// used to store each exponent of a monomial. template< class Exponent, bool HasComponent = true, bool StoreHash = true, bool StoreOrder = true > class MonoMonoid; namespace MonoMonoidInternal { template class Base { public: static const bool HasComponent = HC; static const bool StoreHash = SH; static const bool StoreOrder = SO; typedef size_t VarIndex; typedef E Exponent; typedef typename std::make_unsigned::type Component; typedef typename std::make_unsigned::type HashValue; typedef const Exponent* const_iterator; typedef MonoOrder Order; Base(const Order& order): mVarCount(order.varCount()), mGradingCount( order.gradingCount() + (order.componentBefore() != Order::ComponentAfterBaseOrder) ), mOrderIndexBegin(HasComponent + order.varCount()), mOrderIndexEnd(mOrderIndexBegin + StoreOrder * mGradingCount), mEntryCount(std::max(mOrderIndexEnd + StoreHash, 1)), mHashCoefficients(makeHashCoefficients(order.varCount())), mOrderIsTotalDegreeRevLex( !order.hasLexBaseOrder() && order.isTotalDegree() && order.componentBefore() == Order::ComponentAfterBaseOrder ), mLexBaseOrder(order.hasLexBaseOrder()), mGradings(makeGradings(order)), mComponentGradingIndex( reverseComponentGradingIndex(mGradingCount, order.componentBefore()) ), mVarsReversed(order.hasFromLeftBaseOrder()) { MATHICGB_ASSERT(order.isMonomialOrder()); MATHICGB_ASSERT(mGradings.size() == gradingCount() * varCount()); } VarIndex varCount() const {return mVarCount;} VarIndex gradingCount() const {return mGradingCount;} VarIndex entryCount() const {return mEntryCount;} VarIndex orderIndexEnd() const {return mOrderIndexEnd;} VarIndex orderIndexBegin() const {return mOrderIndexBegin;} VarIndex hashIndex() const {return mOrderIndexEnd;} VarIndex componentGradingIndex() const {return mComponentGradingIndex;} bool varsReversed() const {return mVarsReversed;} protected: typedef std::vector HashCoefficients; typedef std::vector Gradings; static Gradings makeGradings(const Order& order) { auto gradings = order.gradings(); if (order.componentBefore() != Order::ComponentAfterBaseOrder) insertZeroRow(order.varCount(), order.componentBefore(), gradings); reverseGradings(order.varCount(), gradings); if (order.hasFromLeftBaseOrder()) reverseVarsInGradings(order.varCount(), gradings); if (!order.hasLexBaseOrder()) negateGradings(gradings); return gradings; } /// Reverse the relative order among the gradings - the first one /// becomes the last one, the second first becomes the second last /// and so on. static void reverseGradings(const VarIndex varCount, Gradings& gradings) { if (varCount == 0) return; MATHICGB_ASSERT(gradings.size() % varCount == 0); const auto gradingCount = gradings.size() / varCount; for (VarIndex grading = 0; grading < gradingCount / 2; ++grading) { for (VarIndex var = 0; var < varCount; ++var) { const auto index = gradingsIndex(grading, var, varCount); const auto oppositeIndex = gradingsOppositeRowIndex (grading, gradingCount, var, varCount); std::swap(gradings[index], gradings[oppositeIndex]); } } } /// Replace each entry in the grading matrix with its negative. static void negateGradings(Gradings& gradings) { const auto size = gradings.size(); for (size_t i = 0; i < size; ++i) gradings[i] = -gradings[i]; } static void insertZeroRow( const VarIndex varCount, const size_t insertBeforeRow, Gradings& gradings ) { if (varCount == 0) return; MATHICGB_ASSERT(gradings.size() % varCount == 0); MATHICGB_ASSERT(insertBeforeRow <= gradings.size() / varCount); gradings.resize(gradings.size() + varCount); const auto rowBegin = gradings.begin() + insertBeforeRow * varCount; std::copy_backward(rowBegin, gradings.end() - varCount, gradings.end()); std::fill_n(rowBegin, varCount, 0); } static void removeZeroRow( const VarIndex varCount, const size_t row, Gradings& gradings ) { if (varCount == 0) return; MATHICGB_ASSERT(gradings.size() % varCount == 0); MATHICGB_ASSERT(row < gradings.size() / varCount); const auto rowBegin = gradings.begin() + row * varCount; std::copy(rowBegin + varCount, gradings.end(), rowBegin); gradings.resize(gradings.size() - varCount); } /// Replace each row (e_0, e_1, ..., e_n) with (e_n, ..., e_1, e_0). static void reverseVarsInGradings( const size_t varCount, Gradings& gradings ) { if (varCount == 0) return; MATHICGB_ASSERT(gradings.size() % varCount == 0); auto rowBegin = gradings.begin(); while (rowBegin != gradings.end()) { const auto rowEnd = rowBegin + varCount; std::reverse(rowBegin, rowEnd); rowBegin = rowEnd; } } /// Since comparisons go opposite direction, we need to reverse /// the component grading index, unless it's the special value /// indicating that it goes last. static VarIndex reverseComponentGradingIndex( const VarIndex gradingCount, const VarIndex componentGradingIndex ) { if (componentGradingIndex == Order::ComponentAfterBaseOrder) return Order::ComponentAfterBaseOrder; else return gradingCount - 1 - componentGradingIndex; } const HashCoefficients& hashCoefficients() const {return mHashCoefficients;} bool orderIsTotalDegreeRevLex() const {return mOrderIsTotalDegreeRevLex;} Gradings& gradings() {return mGradings;} // todo: remove this overload const Gradings& gradings() const {return mGradings;} bool isLexBaseOrder() const {return mLexBaseOrder;} static size_t gradingsIndex( const VarIndex grading, const VarIndex var, const VarIndex varCount ) { MATHICGB_ASSERT(var < varCount); return grading * static_cast(varCount) + var; } size_t gradingsIndex(const VarIndex grading, const VarIndex var) const { MATHICGB_ASSERT(grading < gradingCount()); MATHICGB_ASSERT(var < varCount()); const auto index = gradingsIndex(grading, var, varCount()); MATHICGB_ASSERT(index < gradings().size()); return index; } static size_t gradingsOppositeRowIndex( const VarIndex grading, const VarIndex gradingCount, const VarIndex var, const VarIndex varCount ) { MATHICGB_ASSERT(grading < gradingCount); MATHICGB_ASSERT(var < varCount); return gradingsIndex(gradingCount - 1 - grading, var, varCount); } size_t gradingsOppositeRowIndex( const VarIndex grading, const VarIndex var ) const { MATHICGB_ASSERT(grading < gradingCount()); MATHICGB_ASSERT(var < varCount()); const auto index = gradingsOppositeRowIndex(grading, gradingCount(), var, varCount()); MATHICGB_ASSERT(index < gradings().size()); return index; } private: HashCoefficients static makeHashCoefficients(const VarIndex varCount) { std::srand(0); // To use the same hash coefficients every time. HashCoefficients coeffs(varCount); for (VarIndex var = 0; var < varCount; ++var) coeffs[var] = static_cast(std::rand()); return coeffs; } const VarIndex mVarCount; const VarIndex mGradingCount; const VarIndex mOrderIndexBegin; const VarIndex mOrderIndexEnd; const VarIndex mEntryCount; const VarIndex mComponentGradingIndex; /// Take dot product of exponents with this vector to get hash value. const HashCoefficients mHashCoefficients; /// This is initialized before mGradings, so it has to be ordered /// above mGradings. const bool mOrderIsTotalDegreeRevLex; /// If true then lex is used to break ties. Otherwise, revlex is /// used. This applies as well to degrees, which implies that /// degrees have to be stored negated if doing revlex. const bool mLexBaseOrder; /// Defines a matrix where each row is a grading. The degree of a /// monomial with respect to grading g is the dot product of the /// exponent vector of that monomial with row g of the matrix /// (starting at g=0). The matrix is stored in row-major order. If /// mOrderIsTotalDegreeRevLex is true then mGradings is empty but /// implicitly it is a single grading consisting of all 1s and the /// base order is revlex. std::vector mGradings; /// All base comparison considers exponents starting from the right, /// yet we need to support base orders starting from the left. This /// is achieved by reversing the order of the variables. The value /// of this variable indicates whether this has happened, in which /// case it needs to be done again before showing a monomial to the /// outside world. const bool mVarsReversed; }; } template class MonoMonoid : private MonoMonoidInternal::Base { private: typedef MonoMonoidInternal::Base Base; public: static_assert(std::numeric_limits::is_signed, ""); // *** Types // Integer index representing a variable. Indices start at 0 and go // up to varCount() - 1 where varCount() is the number of variables. typedef typename Base::VarIndex VarIndex; /// The type of each exponent of a monomial. typedef typename Base::Exponent Exponent; /// Is true if the monomials come from a module. using Base::HasComponent; /// Is true if the hash value is stored rather than computed at each /// hash request. This imposes extra computation when updating a monomial, /// but for most operations that overhead is much less than the time for /// computing a hash value from scratch. using Base::StoreHash; /// Is true if data to compare monomials is stored rather than computed /// at each comparison. As storeHash, there is overhead for this, but it /// is not much for most operations. using Base::StoreOrder; /// Type used to indicate the component of a module monomial. For example, /// the component of xe_3 is 3. typedef typename Base::Component Component; /// Type used to store hash values of monomials. typedef typename Base::HashValue HashValue; /// Iterator for the exponents in a monomial. typedef typename Base::const_iterator const_iterator; /// Represents a monomial and manages the memory underlying it. To /// refer to a non-owned monomial or to refer to a Mono, use MonoRef /// or ConstMonoRef. Do not use Mono& or Mono* if you do not have /// to, since that implies a double indirection when accessing the /// monomial. class Mono; /// A reference to a non-const monomial. Cannot be null, cannot be /// reassigned to refer to a different monomial and does not connote /// ownership - the same semantics as C++ references. class MonoRef; /// A reference to a monomial. As MonoRef, but you cannot change the /// monomial through this reference. Prefer this class over the /// other reference/pointer classes unless there is a reason not to. class ConstMonoRef; /// A pointer to a non-const monomial. Can be null and can be /// reassigned to refer to a different monomial - the same semantics /// as C++ pointers. Does not connote ownership. class MonoPtr; /// A pointer to a monomial. As MonoPtr, but you cannot change the /// monomial through this pointer. class ConstMonoPtr; /// A pool of memory for monomials. /// /// @todo: This approach is a poor fit for variable-sized /// monomials. So prefer other solutions where reasonable. class MonoPool; /// A vector of monomials. The interface is a subset of /// std::vector. Monomials can be appended (push_back). Only the /// last monomial can be mutated and monomials cannot be reordered /// or removed. These restrictions should make it easier to support /// variable-sized monomials in future. Change it if you need to /// break these restrictions, but first try to find an alternative. class MonoVector; /// For indicating the result of comparing one monomial to another. enum CompareResult { LessThan = -1, EqualTo = 0, GreaterThan = 1 }; /// Used to describe a monomial order when constructing a monoid. typedef typename Base::Order Order; // *** Temporary compatibility code for migrating off PolyRing friend class PolyRing; friend class Poly; static MonoRef toRef(Exponent* e) {return MonoRef(e);} static ConstMonoRef toRef(const Exponent* e) {return ConstMonoRef(e);} static Exponent* toOld(MonoRef e) {return rawPtr(e);} static const Exponent* toOld(ConstMonoRef e) {return rawPtr(e);} static Exponent* toOld(Mono& e) {return rawPtr(e);} static const Exponent* toOld(const Mono& e) {return rawPtr(e);} // *** Constructors and accessors MonoMonoid(MonoMonoid&& monoid): Base(std::move(monoid)), mPool(*this) { MATHICGB_ASSERT(debugAssertValid()); } MonoMonoid(const MonoMonoid& monoid): Base(monoid), mPool(*this) { MATHICGB_ASSERT(debugAssertValid()); } MonoMonoid(const Order& order): Base(order), mPool(*this) { MATHICGB_ASSERT(debugAssertValid()); } /// Creates a compatible copy of monoid. template static MonoMonoid create(const MonoMonoid& monoid) { return MonoMonoid(monoid.makeOrder(false, false)); } /// Returns an Order object that is equivalent to the order that /// this monoid was constructed with. The settings not handled by /// the monoid, and therefore not known by the monoid, are passed in /// as parameters. The purpose of that is to make it clear that this /// information must be supplied separately. Order makeOrder( const bool componentsAscendingDesired, const bool schreyering ) const { std::vector orderGradings(gradings()); reverseGradings(varCount(), orderGradings); if (!isLexBaseOrder()) negateGradings(orderGradings); const auto componentIndex = Base::reverseComponentGradingIndex (gradingCount(), componentGradingIndex()); if (componentIndex != Order::ComponentAfterBaseOrder) Base::removeZeroRow(varCount(), componentIndex, orderGradings); return Order( varCount(), std::move(orderGradings), isLexBaseOrder() ? Order::LexBaseOrderFromRight : Order::RevLexBaseOrderFromRight, componentIndex, componentsAscendingDesired, schreyering ); } /// Returns true if higher component is considered greater when /// comparing module monomials. Only relevant once actually /// considering the component. This is only relevant for module /// monomials. bool componentsAscending() const {return isLexBaseOrder();} /// Returns the number of variables. This is also the number of /// exponents in the exponent vector of a monomial. using Base::varCount; /// Returns true if the variables in this ring have been reversed /// so that the first one becomes the last one and so on. Use /// MonoProcessor to reverse monomials for input and output. using Base::varsReversed; // *** Monomial accessors and queries /// Returns iterator to the first exponent. const_iterator begin(ConstMonoRef mono) const { return ptr(mono, exponentsIndexBegin()); } /// Returns iterator to one-past-the-end of the range of exponents. const_iterator end(ConstMonoRef mono) const { return ptr(mono, exponentsIndexEnd()); } /// The indices of variables might be permuted in this monoid in order to /// implement certain monomial orders in a fast way. This method returns /// the unpermuted index that gets permuted to var. Knowing this mapping /// is necessary when importing monomials from and when exporting monomials /// to a party that does not use this scheme. For example when writing a /// monomial to a file in a format that is intended to be readable by /// other programs or by a human. VarIndex externalVar(const VarIndex var) const { // At the moment, this method happens to be its own inverse. Do not depend // on that. MATHICGB_ASSERT(var < varCount()); const auto eVar = varsReversed() ? varCount() - 1 - var : var; MATHICGB_ASSERT(eVar < varCount()); return eVar; } /// The inverse mapping of externalVar(). VarIndex internalVar(const VarIndex var) const { // Do not depend on knowing that this is the implementation. return externalVar(var); } /// Returns the exponent of var in mono. Exponent exponent(ConstMonoRef mono, const VarIndex var) const { MATHICGB_ASSERT(var < varCount()); return access(mono, exponentsIndexBegin() + var); } // The exponent of var as it would be if variables were not permuted. Exponent externalExponent(ConstMonoRef mono, const VarIndex var) const { MATHICGB_ASSERT(var < varCount()); return exponent(mono, externalVar(var)); } /// Returns the component of the monomial. Monomials not from a /// module have component zero. In a module mono*e_i has component /// i. @todo: Have different monoids for module monomials and /// monomials and only offer this method for the module monomials. Component component(ConstMonoRef mono) const { MATHICGB_ASSERT(HasComponent); return access(mono, componentIndex()); } /// Returns a hash value for the monomial. These are not guaranteed /// to be unique. HashValue hash(ConstMonoRef mono) const { MATHICGB_ASSERT(debugHashValid(mono)); if (StoreHash) return static_cast(access(mono, hashIndex())); else return computeHash(mono); } /// Returns true if a and b are equal. Includes check for component. bool equal(ConstMonoRef a, ConstMonoRef b) const { for (auto i = entriesIndexBegin(); i != exponentsIndexEnd(); ++i) if (access(a, i) != access(b, i)) return false; return true; } template bool equal( const MonoidA& monoidA, typename MonoidA::ConstMonoRef a, ConstMonoRef b ) const { // todo: assert compatible for (VarIndex var = 0; var < varCount(); ++var) if (monoidA.exponent(a, var) != exponent(b, var)) return false; return true; } /// As equal(), but optimized for the case where true is returned. bool equalHintTrue(ConstMonoRef a, ConstMonoRef b) const { // if a[i] != b[i] then a[i] ^ b[i] != 0, so the or of all xors is zero // if and only if a equals b. This way we avoid having a branch to check // equality for every iteration of the loop, which is a win in the case // that none of the early-exit branches are taken - that is, when a equals // b. Exponent orOfXor = 0; for (VarIndex i = lastExponentIndex(); i != beforeEntriesIndexBegin(); --i) orOfXor |= access(a, i) ^ access(b, i); MATHICGB_ASSERT((orOfXor == 0) == equal(a, b)); return orOfXor == 0; } bool isProductOf( ConstMonoRef a, ConstMonoRef b, ConstMonoRef ab ) const { for (VarIndex i = entriesIndexBegin(); i != exponentsIndexEnd(); ++i) if (access(ab, i) != access(a, i) + access(b, i)) return false; return true; } bool isProductOfHintTrue( ConstMonoRef a, ConstMonoRef b, ConstMonoRef ab ) const { // We compare more than one exponent at a time using 64 bit integers. This // might go one 32 bit value at the end too far, but since that space is // either a degree or a hash value that is fine --- those values will also // match if the monomials are equal. This does not work for negative // exponents since the overflowing bit will go into the next word. // It is OK that the degree field can be negative (a field we might go // into without caring about it because it shares a 64 bit field with // the last exponent), because it is at the end so the overflowing // bit will not interfere. For this reason we need to have a degree // or a hash value stored there - otherwise two equal monomials could // have different things stored next to them which would confuse this code. // todo: ensure 8 byte alignment. Though there seem to be no ill effects // for unaligned access. Performance seems to be no worse than for using // 32 bit integers directly. if (sizeof(Exponent) != 4 || (!StoreHash && !StoreOrder)) return isProductOf(a, b, ab); uint64 orOfXor = 0; for (VarIndex i = varCount() / 2; i != beforeEntriesIndexBegin(); --i) { MATHICGB_ASSERT(access(a, i*2) >= 0); MATHICGB_ASSERT(i == varCount() / 2 || access(a, i*2+1) >= 0); uint64 A, B, AB; // We have to use std::memcpy here because just casting to a int64 breaks // the strict aliasing rule which implies undefined behavior. Both MSVC and // gcc don't actually call memcpy here. MSVC is a tiny bit slower for this // code than for casting while GCC seems to be exactly the same speed. std::memcpy(&A, ptr(a, i*2), 8); std::memcpy(&B, ptr(b, i*2), 8); std::memcpy(&AB, ptr(ab, i*2), 8); orOfXor |= AB ^ (A + B); } MATHICGB_ASSERT((orOfXor == 0) == isProductOf(a, b, ab)); return orOfXor == 0; } MATHICGB_INLINE bool isTwoProductsOfHintTrue( ConstMonoRef a1, ConstMonoRef a2, ConstMonoRef b, ConstMonoRef a1b, ConstMonoRef a2b ) const { if (sizeof(Exponent) != 4 || (!StoreHash && !StoreOrder)) return (isProductOf(a1, b, a1b) && isProductOf(a2, b, a2b)); uint64 orOfXor = 0; for (VarIndex i = varCount() / 2; i != beforeEntriesIndexBegin(); --i) { uint64 A1, A2, B, A1B, A2B; std::memcpy(&A1, ptr(a1, i*2), 8); std::memcpy(&A2, ptr(a2, i*2), 8); std::memcpy(&B, ptr(b, i*2), 8); std::memcpy(&A1B, ptr(a1b, i*2), 8); std::memcpy(&A2B, ptr(a2b, i*2), 8); orOfXor |= (A1B ^ (A1 + B)) | (A2B ^ (A2 + B)); } MATHICGB_ASSERT ((orOfXor == 0) == (isProductOf(a1, b, a1b) && isProductOf(a2, b, a2b))); return orOfXor == 0; } /// Returns the hash of the product of a and b. HashValue hashOfProduct(ConstMonoRef a, ConstMonoRef b) const { // See computeHash() for an explanation of all the casts. const auto hashA = static_cast(hash(a)); const auto hashB = static_cast(hash(b)); return static_cast(static_cast(hashA + hashB)); } /// Returns true if all the exponents of mono are zero. In other /// words, returns true if mono is the identity for multiplication /// of monomials. bool isIdentity(ConstMonoRef mono) const { return std::all_of(begin(mono), end(mono), [](Exponent e) {return e == 0;}); } /// Returns true if a divides b. Equal monomials divide each other. /// Doesn't take component into account - see dividesWithComponent. bool divides(ConstMonoRef div, ConstMonoRef into) const { // todo: enable this when the code works with it - see // dividesWithComponent. //if (HasComponent && component(div) != component(into)) // return false; for (auto i = exponentsIndexBegin(); i < exponentsIndexEnd(); ++i) if (access(div, i) > access(into, i)) return false; return true; } /// Returns true if a divides b. Equal monomials divide each other. /// This also takes the component into account. Once the code base is /// fixed to properly observe the distinction between monomials and /// module monomials, there will only need to be the one divides() /// which takes component into account if and only if HasComponent is /// true. For now, we're left with this imperfect solution of two /// overloads. /// /// @todo: get rid of this method. bool dividesWithComponent(ConstMonoRef div, ConstMonoRef into) const { if (HasComponent && component(div) != component(into)) return false; for (auto i = exponentsIndexBegin(); i < exponentsIndexEnd(); ++i) if (access(div, i) > access(into, i)) return false; return true; } template bool divides( const MonoidA& monoidA, typename MonoidA::ConstMonoRef a, ConstMonoRef b ) const { // todo: fix other divisibility functions to work properly for component too. MATHICGB_ASSERT(monoidA.varCount() == varCount()); MATHICGB_ASSERT(!MonoidA::HasComponent || HasComponent); MATHICGB_ASSERT(monoidA.debugValid(a)); MATHICGB_ASSERT(debugValid(b)); // todo: enable this when the code works with it //if (HasComponent && component(div) != component(into)) // return false; //if ( // MonoidA::HasComponent && // HasComponent && // monoidA.component(a) != component(b) //) // return false; for (VarIndex var = 0; var < varCount(); ++var) if (monoidA.exponent(a, var) > exponent(b, var)) return false; return true; } /// @todo: get rid of this -- see other overload. template bool dividesWithComponent( const MonoidA& monoidA, typename MonoidA::ConstMonoRef a, ConstMonoRef b ) const { // todo: fix other divisibility functions to work properly for component too. MATHICGB_ASSERT(monoidA.varCount() == varCount()); MATHICGB_ASSERT(!MonoidA::HasComponent || HasComponent); MATHICGB_ASSERT(monoidA.debugValid(a)); MATHICGB_ASSERT(debugValid(b)); if ( MonoidA::HasComponent && HasComponent && monoidA.component(a) != component(b) ) return false; for (VarIndex var = 0; var < varCount(); ++var) if (monoidA.exponent(a, var) > exponent(b, var)) return false; return true; } /// Returns true if div divides lcm(a, b). bool dividesLcm(ConstMonoRef div, ConstMonoRef a, ConstMonoRef b) const { MATHICGB_ASSERT(debugLcmCheck(*this, a, *this, b)); MATHICGB_ASSERT(debugValid(div)); for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) { const auto dive = access(div, i); if (access(div, i) > access(a, i) && access(div, i) > access(b, i)) return false; } return true; } template bool dividesLcm( const MonoidDiv& monoidDiv, typename MonoidDiv::ConstMonoRef div, const MonoidA& monoidA, typename MonoidA::ConstMonoRef a, ConstMonoRef b ) const { MATHICGB_ASSERT(monoidDiv.debugLcmCheck(monoidA, a, *this, b)); MATHICGB_ASSERT(monoidDiv.debugValid(div)); for (VarIndex var = 0; var < varCount(); ++var) { const auto e = monoidDiv.exponent(div, var); if (e > monoidA.exponent(a, var) && e > exponent(b, var)) return false; } return true; } /// Returns true if lcm(a,b) == lcmAB. bool isLcm(ConstMonoRef a, ConstMonoRef b, ConstMonoRef lcmAB) const { MATHICGB_ASSERT(debugLcmCheck(*this, a, *this, b)); MATHICGB_ASSERT(debugValid(lcmAB)); for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) if (access(lcmAB, i) != std::max(access(a, i), access(b, i))) return false; return true; } template bool isLcm( const MonoidA& monoidA, typename MonoidA::ConstMonoRef a, const MonoidB& monoidB, typename MonoidB::ConstMonoRef b, ConstMonoRef lcmAB ) const { MATHICGB_ASSERT(debugLcmCheck(monoidA, a, monoidB, b)); MATHICGB_ASSERT(debugValid(lcmAB)); if (HasComponent) { if (MonoidA::HasComponent) { if (monoidA.component(a) != component(lcmAB)) return false; } else { MATHICGB_ASSERT(MonoidB::HasComponent); if (monoidB.component(b) != component(lcmAB)) return false; } } for (VarIndex var = 0; var < varCount(); ++var) { if ( ptr(lcmAB, exponentsIndexBegin())[var] != std::max(monoidA.exponent(a, var), monoidB.exponent(b, var)) ) return false; } return true; } CompareResult compare(ConstMonoRef a, ConstMonoRef b) const { MATHICGB_ASSERT(debugOrderValid(a)); MATHICGB_ASSERT(debugOrderValid(b)); VarIndex index; if (StoreOrder) index = orderIndexEnd(); else { // Check the degrees seperately since they are not stored. auto grading = gradingCount(); while (grading != 0) { --grading; const auto cmp = degree(a, grading) - degree(b, grading); if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan; if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan; } index = exponentsIndexEnd(); } // If StoreOrder is true then this first checks the degrees. // Then the exponents are checked. // Finally, if HasComponent is true, the component is checked. while (index != entriesIndexBegin()) { --index; const auto cmp = access(a, index) - access(b, index); if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan; if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan; } return EqualTo; } /// Compares a to b1*b2. /// @todo: Test this method. Also, is this method actually useful, or could /// it just as well be replaced by a multiplication and a comparison? CompareResult compare(ConstMonoRef a, ConstMonoRef b1, ConstMonoRef b2) const { MATHICGB_ASSERT(debugOrderValid(a)); MATHICGB_ASSERT(debugOrderValid(b1)); MATHICGB_ASSERT(debugOrderValid(b2)); VarIndex index; if (StoreOrder) index = orderIndexEnd(); else { // Check the degrees seperately since they are not stored. auto grading = gradingCount(); while (grading != 0) { --grading; const auto cmp = degree(a, grading) - (degree(b1, grading) + degree(b2, grading)); if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan; if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan; } index = exponentsIndexEnd(); } // If StoreOrder is true then this first checks the degrees. // Then the exponents are checked. // Finally, if HasComponent is true, the component is checked. while (index != entriesIndexBegin()) { --index; const auto cmp = access(a, index) - (access(b1, index) + access(b2, index)); if (cmp < 0) return isLexBaseOrder() ? LessThan : GreaterThan; if (cmp > 0) return isLexBaseOrder() ? GreaterThan : LessThan; } return EqualTo; } bool lessThan(ConstMonoRef a, ConstMonoRef b) const { return compare(a, b) == LessThan; } /// Returns true if gcd(a, b) == 1. bool relativelyPrime(ConstMonoRef a, ConstMonoRef b) const { for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) if (access(a, i) > 0 && access(b, i) > 0) return false; return true; } // If this method returns true for monomials a and b then it is // guaranteed that multiplying a and b together will not overflow // the integers in the representation. bool hasAmpleCapacity(ConstMonoRef mono) const { const auto halfMin = std::numeric_limits::min() / 2; const auto halfMax = std::numeric_limits::max() / 2; MATHICGB_ASSERT(halfMin <= 0); const auto limit = std::min(-halfMin, halfMax); const auto inRange = [&](Exponent value) {return -limit <= value && value <= limit;}; for (VarIndex i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) if (!inRange(access(mono, i))) return false; for (VarIndex grading = 0; grading < gradingCount(); ++grading) if (!inRange(degree(mono, grading))) return false; return true; } /// Returns the degree of mono using the most significant grading on /// the monoid. This is the grading with index gradingCount() - /// 1. This object must have at least one grading associated to it /// before calling this method. Exponent degree(ConstMonoRef mono) const { MATHICGB_ASSERT(gradingCount() > 0); return degree(mono, gradingCount() - 1); } /// Returns the degree of mono according to the grading with the /// given index. Exponent degree(ConstMonoRef mono, VarIndex grading) const { MATHICGB_ASSERT(grading < gradingCount()); MATHICGB_ASSERT(debugOrderValid(mono)); if (StoreOrder) return access(mono, orderIndexBegin() + grading); else return computeDegree(mono, grading); } /// Returns the number of gradings. using Base::gradingCount; /// Returns the number of entries per monomial. This includes entries /// used fo r internal book-keeping, so it can be greater than varCount(). using Base::entryCount; // *** Monomial mutating computations /// Copes the parameter from to the parameter to. void copy(ConstMonoRef from, MonoRef to) const { MATHICGB_ASSERT(debugValid(from)); std::copy_n(rawPtr(from), entryCount(), rawPtr(to)); MATHICGB_ASSERT(debugValid(to)); } template void copy( const MonoidFrom& monoidFrom, typename MonoidFrom::ConstMonoRef from, MonoRef to ) const { // todo: extract this in checker method MATHICGB_ASSERT(HasComponent == MonoidFrom::HasComponent); MATHICGB_ASSERT(monoidFrom.debugValid(from)); MATHICGB_ASSERT(monoidFrom.varCount() == varCount()); MATHICGB_ASSERT(monoidFrom.varsReversed() == varsReversed()); MATHICGB_ASSERT ((std::is_same::value)); if (HasComponent) access(to, componentIndex()) = monoidFrom.component(from); const auto expsTo = ptr(to, exponentsIndexBegin()); for (VarIndex var = 0; var < varCount(); ++var) expsTo[var] = monoidFrom.exponent(from, var); if (StoreOrder) { const auto degrees = ptr(to, orderIndexBegin()); for (VarIndex grading = 0; grading < gradingCount(); ++grading) degrees[grading] = monoidFrom.degree(from, grading); } if (StoreHash) access(to, hashIndex()) = monoidFrom.hash(from); MATHICGB_ASSERT(debugValid(to)); // todo: check equal } /// Set the exponent of var to newExponent in mono. void setExponent( const VarIndex var, const Exponent newExponent, MonoRef mono ) const { MATHICGB_ASSERT(var < varCount()); auto& exponent = access(mono, exponentsIndexBegin() + var); const auto oldExponent = exponent; exponent = newExponent; updateOrderData(var, oldExponent, newExponent, mono); updateHashExponent(var, oldExponent, newExponent, mono); MATHICGB_ASSERT(debugValid(mono)); } /// Sets an exponent based on external/unpermtuted var. /// After this, exponent(mono, internvalVar(exVar)) is newExponent. void setExternalExponent( const VarIndex exVar, const Exponent newExponent, MonoRef mono ) const { setExponent(internalVar(exVar), newExponent, mono); } /// Sets all the exponents of mono from an external/unpermuted array. /// exponents must point to an array of size varCount(). /// After this, exponent(mono, var) is exponents[externalVar(var)]. /// The value of exponents[var] becomes the exponent of internalVar(var). /// Does not set the component. void setExternalExponents(const Exponent* exponents, MonoRef mono) const { MATHICGB_ASSERT(exponents != 0); for (VarIndex iVar = 0; iVar < varCount(); ++iVar) { const auto eVar = externalVar(iVar); access(mono, exponentsIndexBegin() + iVar) = exponents[eVar]; } setOrderData(mono); setHash(mono); MATHICGB_ASSERT(debugValid(mono)); } /// Sets mono to 1, which is the identity for multiplication. void setIdentity(MonoRef mono) const { std::fill_n(rawPtr(mono), entryCount(), 0); MATHICGB_ASSERT(debugValid(mono)); MATHICGB_ASSERT(isIdentity(mono)); } /// Sets the component of mono to newComponent. void setComponent(Component newComponent, MonoRef mono) const { MATHICGB_ASSERT(HasComponent); auto& component = access(mono, componentIndex()); const auto oldComponent = component; component = newComponent; updateHashComponent(oldComponent, newComponent, mono); updateOrderComponent(newComponent, mono); MATHICGB_ASSERT(debugValid(mono)); } /// Sets prod to a*b. void multiply(ConstMonoRef a, ConstMonoRef b, MonoRef prod) const { MATHICGB_ASSERT(debugValid(a)); MATHICGB_ASSERT(debugValid(b)); for (auto i = lastEntryIndex(); i != beforeEntriesIndexBegin(); --i) access(prod, i) = access(a, i) + access(b, i); MATHICGB_ASSERT(debugValid(prod)); } /// Sets prod to a*prod. void multiplyInPlace(ConstMonoRef a, MonoRef prod) const { MATHICGB_ASSERT(debugValid(a)); MATHICGB_ASSERT(debugValid(prod)); for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i) access(prod, i) += access(a, i); MATHICGB_ASSERT(debugValid(prod)); } /// Sets quo to num/by. by must divide num. void divide(ConstMonoRef by, ConstMonoRef num, MonoRef quo) const { MATHICGB_ASSERT(divides(by, num)); MATHICGB_ASSERT(debugValid(num)); MATHICGB_ASSERT(debugValid(by)); for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i) access(quo, i) = access(num, i) - access(by, i); MATHICGB_ASSERT(debugValid(quo)); } /// Sets num to num/by. by must divide num. void divideInPlace(ConstMonoRef by, MonoRef num) const { MATHICGB_ASSERT(divides(by, num)); MATHICGB_ASSERT(debugValid(by)); MATHICGB_ASSERT(debugValid(num)); for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i) access(num, i) -= access(by, i); MATHICGB_ASSERT(debugValid(num)); } /// Sets quo to num/by. If by does not divide num then quo will have /// negative exponents. void divideToNegative(ConstMonoRef by, ConstMonoRef num, MonoRef quo) const { MATHICGB_ASSERT(debugValid(num)); MATHICGB_ASSERT(debugValid(by)); MATHICGB_ASSERT( !HasComponent || component(by) == 0 || component(by) == component(num) ); for (auto i = entriesIndexBegin(); i < entriesIndexEnd(); ++i) access(quo, i) = access(num, i) - access(by, i); MATHICGB_ASSERT(debugValid(quo)); } /// Set out to (colonBy : colonNum) * mult. /// @todo: test void colonMultiply( ConstMonoRef colonBy, ConstMonoRef colonNum, ConstMonoRef mult, MonoRef out ) const { // todo: consider what happens with exponent overflow here if (HasComponent) { MATHICGB_ASSERT(component(colonBy) == component(colonNum)); access(out, componentIndex()) = component(mult); } for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) { const auto colon = access(colonNum, i) - access(colonBy, i); auto result = access(mult, i); if (colon > 0) result += colon; access(out, i) = result; } setOrderData(out); setHash(out); MATHICGB_ASSERT(debugValid(out)); } /// Returns the number of variables that divide mono. /// @todo: test VarIndex sizeOfSupport(ConstMonoRef mono) const { VarIndex count = 0; for (VarIndex var = 0; var < varCount(); ++var) if (exponent(mono, var) != 0) ++count; return count; } /// Sets aColonB to a:b and bColonA to b:a. void colons( ConstMonoRef a, ConstMonoRef b, MonoRef aColonB, MonoRef bColonA ) const { MATHICGB_ASSERT(debugValid(a)); MATHICGB_ASSERT(debugValid(b)); if (HasComponent) { MATHICGB_ASSERT(component(a) == component(b)); access(aColonB, componentIndex()) = 0; access(bColonA, componentIndex()) = 0; } for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) { const auto ae = access(a, i); const auto be = access(b, i); const auto max = std::max(ae, be); access(aColonB, i) = max - be; access(bColonA, i) = max - ae; } setOrderData(aColonB); setHash(aColonB); setOrderData(bColonA); setHash(bColonA); MATHICGB_ASSERT(debugValid(aColonB)); MATHICGB_ASSERT(debugValid(bColonA)); } /// Sets lcmAB to the lcm of a and b. void lcm(ConstMonoRef a, ConstMonoRef b, MonoRef lcmAB) const { if (HasComponent) { MATHICGB_ASSERT(component(a) == component(b)); access(lcmAB, componentIndex()) = access(a, componentIndex()); } for (auto i = exponentsIndexBegin(); i != exponentsIndexEnd(); ++i) access(lcmAB, i) = std::max(access(a, i), access(b, i)); setOrderData(lcmAB); setHash(lcmAB); MATHICGB_ASSERT(debugValid(lcmAB)); MATHICGB_ASSERT(isLcm(a, b, lcmAB)); } template void lcm( const MonoidA& monoidA, typename MonoidA::ConstMonoRef a, const MonoidB& monoidB, typename MonoidB::ConstMonoRef b, MonoRef lcmAB ) const { MATHICGB_ASSERT(debugLcmCheck(monoidA, a, monoidB, b)); if (HasComponent) { access(lcmAB, componentIndex()) = MonoidA::HasComponent ? monoidA.component(a) : monoidB.component(b); } for (VarIndex var = 0; var < varCount(); ++var) { ptr(lcmAB, exponentsIndexBegin())[var] = std::max(monoidA.exponent(a, var), monoidB.exponent(b, var)); } setOrderData(lcmAB); setHash(lcmAB); MATHICGB_ASSERT(debugValid(lcmAB)); MATHICGB_ASSERT(isLcm(monoidA, a, monoidB, b, lcmAB)); } Mono alloc() const {return mPool.alloc();} void free(Mono&& mono) const {mPool.free(std::move(mono));} void freeRaw(MonoRef mono) const {mPool.freeRaw(mono);} void freeRaw(MonoPtr mono) const { if (mono != nullptr) freeRaw(*mono); } bool fromPool(ConstMonoRef mono) const {return mPool.fromPool(mono);} // *** Classes for holding and referring to monomials class ConstMonoPtr { public: ConstMonoPtr(): mMono(nullptr) {} ConstMonoPtr(std::nullptr_t): mMono(nullptr) {} ConstMonoPtr(const ConstMonoPtr& mono): mMono(rawPtr(mono)) {} ConstMonoPtr operator=(const ConstMonoPtr& mono) { mMono = mono.mMono; return *this; } ConstMonoRef operator*() const {return ConstMonoRef(*this);} /// @todo: Get rid of this as soon as all code has been migrated /// to observe the ptr/ref distinction. Kill it with fire! operator ConstMonoRef() const {return ConstMonoRef(*this);} bool isNull() const {return mMono == nullptr;} void toNull() {mMono = nullptr;} bool operator==(std::nullptr_t) const {return isNull();} bool operator!=(std::nullptr_t) const {return !isNull();} MonoPtr castAwayConst() const { return MonoPtr(const_cast(mMono)); } private: friend class MonoMonoid; const Exponent* internalRawPtr() const {return mMono;} ConstMonoPtr(const Exponent* mono): mMono(mono) {} const Exponent* mMono; }; class MonoPtr { public: MonoPtr(): mMono(nullptr) {} MonoPtr(std::nullptr_t): mMono(nullptr) {} MonoPtr(const MonoPtr& mono): mMono(mono.mMono) {} MonoPtr operator=(const MonoPtr& mono) { mMono = mono.mMono; return *this; } MonoRef operator*() const {return MonoRef(*this);} /// @todo: Get rid of this as soon as all code has been migrated /// to observe the ptr/ref distinction. Kill it with fire! operator MonoRef() const {return MonoRef(*this);} bool isNull() const {return mMono == nullptr;} void toNull() {mMono = nullptr;} bool operator==(std::nullptr_t) const {return isNull();} bool operator!=(std::nullptr_t) const {return !isNull();} operator ConstMonoPtr() const {return ConstMonoPtr(mMono);} private: friend class MonoMonoid; friend class ConstMonoPtr; friend class PolyRing; // todo: remove friend class Poly; // todo: remove Exponent* internalRawPtr() const {return mMono;} MonoPtr(Exponent* mono): mMono(mono) {} Exponent* mMono; }; class Mono : public NonCopyable { public: Mono(): mMono(), mPool(nullptr) {} Mono(std::nullptr_t): mMono(), mPool(nullptr) {} /// Passes ownership of the resources of mono to this object. Mono must /// have been allocated from pool and it must have no other owner. /// In particular, it must have been release()'ed from its original /// owner. Mono(MonoRef mono, MonoPool& pool): mMono(mono.ptr()), mPool(&pool) { MATHICGB_ASSERT(pool.fromPool(mono)); } Mono(Mono&& mono): mMono(mono.mMono), mPool(mono.mPool) { mono.mMono.toNull(); mono.mPool = nullptr; } ~Mono() {toNull();} void operator=(Mono&& mono) { toNull(); mMono = mono.mMono; mono.mMono.toNull(); mPool = mono.mPool; mono.mPool = nullptr; } /// Sets this object to null but does NOT free the resources previously /// held by this object. The returned MonoPtr points to the resources /// that this object had prior to calling release(). If this object was /// already null then the returned MonoPtr is also null. MonoPtr release() { const auto oldPtr = ptr(); mMono.toNull(); mPool = nullptr; return oldPtr; } bool isNull() const {return mMono.isNull();} void toNull() {mPool->free(std::move(*this));} MonoPtr ptr() {return mMono;} ConstMonoPtr ptr() const {return mMono;} MonoRef operator*() { MATHICGB_ASSERT(!isNull()); return *mMono; } ConstMonoRef operator*() const { MATHICGB_ASSERT(!isNull()); return *mMono; } operator MonoPtr() const {return ptr();} operator ConstMonoPtr() const {return ptr();} /// @todo: Get rid of this as soon as all code has been migrated /// to observe the ptr/ref distinction. Kill it with fire! operator MonoRef() const { MATHICGB_ASSERT(!isNull()); return *mMono; } /// @todo: Get rid of this as soon as all code has been migrated /// to observe the ptr/ref distinction. Kill it with fire! operator ConstMonoRef() const { MATHICGB_ASSERT(!isNull()); return *mMono; } private: friend class MonoMonoid; Exponent* internalRawPtr() const {return rawPtr(mMono);} MonoPtr mMono; MonoPool* mPool; }; class MonoRef { public: MonoRef(const MonoRef& mono): mMono(mono.ptr()) {} MonoPtr ptr() const {return mMono;} MonoPtr operator&() const {return ptr();} /// @todo: Get rid of this as soon as all code has been migrated /// to observe the ptr/ref distinction. Kill it with fire! operator MonoPtr() const {return ptr();} operator ConstMonoRef() const {return *static_cast(mMono);} private: void operator=(const MonoRef&); // not available friend class MonoMonoid; friend class ConstMonoRef; MonoRef(MonoPtr mono): mMono(mono) {} Exponent* internalRawPtr() const {return rawPtr(mMono);} const MonoPtr mMono; }; class ConstMonoRef { public: ConstMonoRef(const ConstMonoRef& mono): mMono(mono.ptr()) {} ConstMonoRef(const Mono& mono): mMono(mono.ptr()) { MATHICGB_ASSERT(!mono.isNull()); } ConstMonoPtr ptr() const {return mMono;} ConstMonoPtr operator&() const {return ptr();} /// @todo: Get rid of this as soon as all code has been migrated /// to observe the ptr/ref distinction. Kill it with fire! operator ConstMonoPtr() const {return ptr();} MonoRef castAwayConst() const {return MonoRef(mMono.castAwayConst());} private: void operator=(const MonoRef&); // not available friend class MonoMonoid; ConstMonoRef(ConstMonoPtr mono): mMono(mono) {} const Exponent* internalRawPtr() const {return rawPtr(mMono);} const ConstMonoPtr mMono; }; // *** Classes that provide memory resources for monomials class MonoPool : public NonCopyable { public: MonoPool(const MonoMonoid& monoid): mMonoid(monoid), mPool(sizeof(Exponent) * mMonoid.entryCount()) {} MonoPool(MonoPool&& pool): mMonoid(pool.mMonoid), mPool(std::move(pool.mPool)) {} Mono alloc() { const auto ptr = static_cast(mPool.alloc()); Mono mono(*MonoPtr(ptr), *this); monoid().setIdentity(mono); return mono; } void free(Mono&& mono) { if (mono.isNull()) return; freeRaw(mono); mono.mMono.toNull(); mono.mPool = nullptr; } void freeRaw(MonoRef mono) {mPool.free(rawPtr(mono));} const MonoMonoid& monoid() const {return mMonoid;} bool fromPool(ConstMonoRef mono) const { return mPool.fromPool(rawPtr(mono)); } private: const MonoMonoid& mMonoid; memt::BufferPool mPool; }; class MonoVector { private: typedef std::vector RawVector; public: /// Class for iterating through the monomials in a MonoVector. /// /// There is no operator->() since MonoRef does not have any /// relevant methods to call. Implement it if you need it. /// /// There are no postfix increment operator as prefix is /// better. Add it if you need it (you probably do not). /// /// We could make this a random access iterator, but that would /// make it tricky to support variable-sized exponent vectors /// (e.g. sparse) in future and so far we have not needed random /// access. class const_iterator { public: typedef std::forward_iterator_tag iterator_category; typedef ConstMonoRef value_type; typedef ptrdiff_t difference_type; typedef ConstMonoPtr pointer; typedef ConstMonoRef reference; const_iterator(): mIt(), mEntriesPerMono(0) {} const_iterator(const const_iterator& it): mIt(it.mIt), mEntriesPerMono(it.mEntriesPerMono) {} bool operator==(const const_iterator& it) const {return mIt == it.mIt;} bool operator!=(const const_iterator& it) const {return mIt != it.mIt;} ConstMonoRef operator*() const { MATHICGB_ASSERT(debugValid()); return *ConstMonoPtr(&*mIt); } const_iterator operator++() { MATHICGB_ASSERT(debugValid()); mIt += mEntriesPerMono; return *this; } private: friend class MonoVector; bool debugValid() const {return mEntriesPerMono > 0;} const_iterator( typename RawVector::const_iterator it, size_t entryCount ): mIt(it), mEntriesPerMono(entryCount) {} typename RawVector::const_iterator mIt; size_t mEntriesPerMono; }; // *** Constructors and assignment MonoVector(const MonoMonoid& monoid): mMonoid(monoid) {} MonoVector(const MonoVector& v): mMonos(v.mMonos), mMonoid(v.monoid()) {} MonoVector(MonoVector&& v): mMonos(std::move(v.mMonos)), mMonoid(v.monoid()) {} MonoVector& operator=(const MonoVector& v) { MATHICGB_ASSERT(monoid() == v.monoid()); mMonos = v.mMonos; return *this; } MonoVector& operator=(MonoVector&& v) { MATHICGB_ASSERT(monoid() == v.monoid()); mMonos = std::move(v.mMonos); return *this; } // *** Iterators const_iterator begin() const { return const_iterator(mMonos.begin(), mMonoid.entryCount()); } const_iterator end() const { return const_iterator(mMonos.end(), mMonoid.entryCount()); } const_iterator cbegin() const {return begin();} const_iterator cend() const {return end();} // *** Operators /// Returns true if *this and v contain the same monomials in the same /// order. This ought to be a free-standing function, but it cannot be, /// because template argument deduction cannot deduce a type T from /// something of the form A::MonoVector. bool operator==(const MonoVector& v) const { MATHICGB_ASSERT(monoid() == v.monoid()); return mMonos == v.mMonos; } /// As !(*this == v). bool operator!=(const MonoVector& v) const { MATHICGB_ASSERT(monoid() == v.monoid()); return !(*this == v); } // *** Size and capacity size_t size() const {return mMonos.size() / monoid().entryCount();} bool empty() const {return mMonos.empty();} size_t capacity() const {return mMonos.capacity() / monoid().entryCount();} bool atCapacity() const {return size() == capacity();} // *** Element access ConstMonoRef front() const { MATHICGB_ASSERT(!empty()); return *begin(); } MonoRef back() { MATHICGB_ASSERT(!empty()); const auto offset = mMonos.size() - monoid().entryCount(); return *MonoPtr(mMonos.data() + offset); } ConstMonoRef back() const { MATHICGB_ASSERT(!empty()); const auto offset = mMonos.size() - monoid().entryCount(); return *ConstMonoPtr(mMonos.data() + offset); } // *** Modifiers void reserve(size_t count) { mMonos.reserve(count * monoid().entryCount()); } /// Appends the identity. void push_back() { const auto offset = mMonos.size(); mMonos.resize(offset + monoid().entryCount()); MATHICGB_ASSERT(monoid().isIdentity(back())); MATHICGB_ASSERT(monoid().debugValid(back())); } void push_back(ConstMonoRef mono) { MATHICGB_ASSERT(monoid().debugValid(mono)); const auto offset = mMonos.size(); mMonos.resize(offset + monoid().entryCount()); monoid().copy(mono, *MonoPtr(mMonos.data() + offset)); MATHICGB_ASSERT(monoid().debugValid(back())); MATHICGB_ASSERT(monoid().equal(back(), mono)); } template void push_back( const Monoid& monoidMono, typename Monoid::ConstMonoRef mono ) { MATHICGB_ASSERT(monoidMono.debugValid(mono)); const auto offset = mMonos.size(); mMonos.resize(offset + monoid().entryCount()); monoid().copy(monoidMono, mono, *MonoPtr(mMonos.data() + offset)); MATHICGB_ASSERT(monoid().debugValid(back())); MATHICGB_ASSERT(monoid().equal(monoidMono, mono, back())); } void swap(MonoVector& v) { MATHICGB_ASSERT(monoid() == v.monoid()); mMonos.swap(v.mMonos); } void clear() {mMonos.clear();} // *** Other size_t memoryBytesUsed() const { return mMonos.capacity() * sizeof(mMonos.front()); } const MonoMonoid& monoid() const {return mMonoid;} private: RawVector mMonos; const MonoMonoid& mMonoid; }; bool debugValid(ConstMonoRef mono) const { MATHICGB_ASSERT(debugOrderValid(mono)); MATHICGB_ASSERT(debugHashValid(mono)); return true; } private: void operator=(MonoMonoid&); // not available // Grants access to other template instantiations. template friend class MonoMonoid; // The main point here is to grant access to rawPtr(). friend class Mono; friend class MonoRef; friend class ConstMonoRef; friend class MonoPtr; friend class ConstMonoPtr; friend class MonoVector; friend class MonoPool; friend class PolyHashTable; typedef typename Base::Gradings Gradings; bool debugAssertValid() const { #ifdef MATHICGB_DEBUG // ** Order checks MATHICGB_ASSERT(orderIndexBegin() == exponentsIndexEnd()); const auto storedDegrees = StoreOrder * gradingCount(); MATHICGB_ASSERT(orderIndexEnd() == orderIndexBegin() + storedDegrees); MATHICGB_ASSERT(orderIndexEnd() <= entryCount()); if (orderIndexEnd() + StoreHash == 0) { MATHICGB_ASSERT(entryCount() == 1); } else { MATHICGB_ASSERT(entryCount() == orderIndexEnd() + StoreHash); } MATHICGB_ASSERT(isLexBaseOrder() || varCount() == 0 || gradingCount() >= 1); MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount()); if (orderIsTotalDegreeRevLex()) { MATHICGB_ASSERT(!isLexBaseOrder()); MATHICGB_ASSERT(gradingCount() == 1); } if (componentGradingIndex() != Order::ComponentAfterBaseOrder) { MATHICGB_ASSERT(componentGradingIndex() < gradingCount()); for (VarIndex var = 0; var < varCount(); ++var) { const auto index = gradingsIndex(componentGradingIndex(), var); MATHICGB_ASSERT(gradings()[index] == 0); } } // ** Hash checks if (StoreHash) { MATHICGB_ASSERT(hashIndex() < entryCount()); MATHICGB_ASSERT(hashIndex() == orderIndexEnd()); } MATHICGB_ASSERT(hashCoefficients().size() == varCount()); #endif return true; } template bool debugLcmCheck( const MonoidA& monoidA, typename MonoidA::ConstMonoRef a, const MonoidB& monoidB, typename MonoidB::ConstMonoRef b ) const { MATHICGB_ASSERT(monoidA.varCount() == varCount()); MATHICGB_ASSERT(monoidB.varCount() == varCount()); MATHICGB_ASSERT ((std::is_same::value)); MATHICGB_ASSERT ((std::is_same::value)); MATHICGB_ASSERT (HasComponent == (MonoidA::HasComponent || MonoidB::HasComponent)); MATHICGB_ASSERT(monoidA.debugValid(a)); MATHICGB_ASSERT(monoidB.debugValid(b)); MATHICGB_ASSERT( !HasComponent || !MonoidA::HasComponent || !MonoidB::HasComponent || monoidA.component(a) == monoidB.component(b) ); return true; } static MonoPtr toMonoPtr(Exponent* raw) {return MonoPtr(raw);} static ConstMonoPtr toMonoPtr(const Exponent* raw) { return ConstMonoPtr(raw); } // *** Accessing fields of a monomial template static auto rawPtr(M&& m) -> decltype(m.internalRawPtr()) { return m.internalRawPtr(); } Exponent* ptr(MonoRef& m, const VarIndex index) const { MATHICGB_ASSERT(index <= entryCount()); return rawPtr(m) + index; } const Exponent* ptr(ConstMonoRef& m, const VarIndex index) const { MATHICGB_ASSERT(index <= entryCount()); return rawPtr(m) + index; } Exponent& access(MonoRef& m, const VarIndex index) const { MATHICGB_ASSERT(index < entryCount()); return rawPtr(m)[index]; } const Exponent& access(ConstMonoRef& m, const VarIndex index) const { MATHICGB_ASSERT(index < entryCount()); return rawPtr(m)[index]; } // *** Implementation of monomial ordering using Base::gradingsOppositeRowIndex; using Base::gradingsIndex; using Base::reverseGradings; using Base::negateGradings; bool debugOrderValid(ConstMonoRef mono) const { #ifdef MATHICGB_DEBUG if (!StoreOrder) return true; // Check the order data of mono const auto degrees = ptr(mono, orderIndexBegin()); for (VarIndex grading = 0; grading < gradingCount(); ++grading) { MATHICGB_ASSERT(degrees[grading] == computeDegree(mono, grading)); } #endif return true; } void setOrderData(MonoRef mono) const { if (!StoreOrder) return; const auto degrees = ptr(mono, orderIndexBegin()); for (VarIndex grading = 0; grading < gradingCount(); ++grading) degrees[grading] = computeDegree(mono, grading); MATHICGB_ASSERT(debugOrderValid(mono)); } void updateOrderData( const VarIndex var, const Exponent oldExponent, const Exponent newExponent, MonoRef mono ) const { if (!StoreOrder) return; MATHICGB_ASSERT(var < varCount()); if (orderIsTotalDegreeRevLex()) rawPtr(mono)[orderIndexBegin()] -= newExponent - oldExponent; else { MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount()); const auto degrees = ptr(mono, orderIndexBegin()); for (VarIndex grading = 0; grading < gradingCount(); ++grading) { const auto index = gradingsIndex(grading, var); degrees[grading] += gradings()[index] * ( newExponent - oldExponent); } } MATHICGB_ASSERT(debugOrderValid(mono)); } void updateOrderComponent(const VarIndex newComponent, MonoRef mono) const { if (componentGradingIndex() != Order::ComponentAfterBaseOrder) ptr(mono, orderIndexBegin())[componentGradingIndex()] = static_cast(newComponent); } Exponent computeDegree(ConstMonoRef mono, VarIndex grading) const { MATHICGB_ASSERT(grading < gradingCount()); Exponent degree = 0; if (orderIsTotalDegreeRevLex()) { MATHICGB_ASSERT(grading == 0); for (auto var = size_t(0); var < varCount(); ++var) degree -= exponent(mono, var); } else if (HasComponent && componentGradingIndex() == grading) return component(mono); else { MATHICGB_ASSERT(gradings().size() == gradingCount() * varCount()); for (auto var = size_t(0); var < varCount(); ++var) { const auto index = gradingsIndex(grading, var); degree += exponent(mono, var) * gradings()[index]; } } return degree; } // *** Implementation of hash value computation bool debugHashValid(ConstMonoRef mono) const { if (!StoreHash) return true; // We cannot call hash() here since it calls this method. // todo: we cannot make this check right now because the legacy // integration with PolyRing can create monomials with unset hash. // MATHICGB_ASSERT(rawPtr(mono)[hashIndex()] == computeHash(mono)); return true; } HashValue computeHash(ConstMonoRef mono) const { HashValue hash = HasComponent ? component(mono) : 0; for (VarIndex var = 0; var < varCount(); ++var) { hash += static_cast(exponent(mono, var)) * hashCoefficients()[var]; } // Hash values are stored as exponents. If the cast to an exponent // changes the value, then we need computeHashValue to match that // change by casting to an exponent and back. Otherwise the computed // hash value will not match a hash value that has been stored. return static_cast(static_cast(hash)); } void setHash(MonoRef mono) const { if (!StoreHash) return; rawPtr(mono)[hashIndex()] = computeHash(mono); MATHICGB_ASSERT(debugHashValid(mono)); } void updateHashComponent( const Exponent oldComponent, const Exponent newComponent, MonoRef mono ) const { if (!StoreHash) return; rawPtr(mono)[hashIndex()] += newComponent - oldComponent; MATHICGB_ASSERT(debugHashValid(mono)); } void updateHashExponent( const VarIndex var, const Exponent oldExponent, const Exponent newExponent, MonoRef mono ) const { if (!StoreHash) return; MATHICGB_ASSERT(var < varCount()); rawPtr(mono)[hashIndex()] += (newExponent - oldExponent) * hashCoefficients()[var]; MATHICGB_ASSERT(debugHashValid(mono)); } // *** Code determining the layout of monomials in memory // Layout in memory: // [component] [exponents...] [order data...] [hash] VarIndex componentIndex() const { //static_assert(HasComponent, ""); return 0; } VarIndex exponentsIndexBegin() const {return HasComponent;} VarIndex exponentsIndexEnd() const {return exponentsIndexBegin() + varCount();} VarIndex lastExponentIndex() const {return exponentsIndexEnd() - 1;} using Base::orderIndexBegin; using Base::orderIndexEnd; using Base::hashIndex; using Base::orderIsTotalDegreeRevLex; using Base::gradings; using Base::isLexBaseOrder; using Base::componentGradingIndex; VarIndex entriesIndexBegin() const {return 0;} VarIndex entriesIndexEnd() const {return entryCount();} VarIndex beforeEntriesIndexBegin() const {return entriesIndexBegin() - 1;} VarIndex lastEntryIndex() const {return entriesIndexEnd() - 1;} using Base::hashCoefficients; mutable MonoPool mPool; }; /// Returns true if a and b are the same object. template bool operator==( const MonoMonoid& a, const MonoMonoid& b ) { return &a == &b; } /// As !(a == b). template bool operator!=( const MonoMonoid& a, const MonoMonoid& b ) { return !(a == b); } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/MonoOrder.hpp000077500000000000000000000146421311555162500211250ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MONO_ORDER_GUARD #define MATHICGB_MONO_ORDER_GUARD #include #include MATHICGB_NAMESPACE_BEGIN /// Class used to describe an monomial order and/or a module monomial /// order. Use this class to construct a monoid. The monoid does the /// actual comparisons. Monomials must be preprocessed by MonoProcessor - /// otherwise the ordering may not be correct. MonoProcessor also offers /// additional parameters for making orders. template class MonoOrder; template class MonoOrder { public: typedef W Weight; typedef size_t VarIndex; typedef std::vector Gradings; static const size_t ComponentAfterBaseOrder = static_cast(-1); enum BaseOrder { /// Lexicographic order with x_0 < x_1 < ... < x_n. LexBaseOrderFromRight = 0, /// Reverse lexicographic order with x_0 > x_1 > ... > x_n. RevLexBaseOrderFromRight = 1, /// Lexicographic order with x_0 > x_1 > ... > x_n. LexBaseOrderFromLeft = 2, /// Reverse lexicographic order with x_0 < x_1 < ... < x_n. RevLexBaseOrderFromLeft = 3 }; /// The specified base order is graded by the gradings matrix. /// /// The layout of the gradings matrix is row-major. For comparisons, /// the degree with respect to the first row is considered first, /// then the degree with respect to the second row and so on. The /// base order is used as a tie-breaker. The gradings vector can be /// empty. The order must be a monomial order - in particular, 1 /// must be strictly less than all other monomials. /// /// For module monomials, the component is considered too. When the /// component is considered depends on componentBefore. If /// componentBefore == 0 then the component is considered before /// anything else. If componentBefore < gradingCount(), then the /// component is considered before the grading with index /// componentBefore and after the grading with index componentBefore /// - 1. If componentBefore == gradingCount(), then the component is /// considered after all gradings and before the base order. If /// componentBefore = ComponentAfterBaseOrder then the component is /// considered after everything else, including afte the base order. MonoOrder( const VarIndex varCount, Gradings&& gradings, const BaseOrder baseOrder = RevLexBaseOrderFromRight, const size_t componentBefore = ComponentAfterBaseOrder, const bool componentsAscendingDesired = true, const bool schreyering = true ): mVarCount(varCount), mGradings(std::move(gradings)), mBaseOrder(baseOrder), mComponentBefore(componentBefore), mComponentsAscendingDesired(componentsAscendingDesired), mSchreyering(schreyering) { MATHICGB_ASSERT(debugAssertValid()); } /// Same as MonoOrder(varCount, varOrder, gradings, componentBefore) /// where gradings has a single row of varCount 1's. MonoOrder( const VarIndex varCount, const BaseOrder baseOrder = RevLexBaseOrderFromRight, const size_t componentBefore = ComponentAfterBaseOrder, const bool componentsAscendingDesired = true, const bool schreyering = true ): mVarCount(varCount), mGradings(varCount, 1), mBaseOrder(baseOrder), mComponentBefore(componentBefore), mComponentsAscendingDesired(componentsAscendingDesired), mSchreyering(schreyering) { MATHICGB_ASSERT(debugAssertValid()); } VarIndex varCount() const {return mVarCount;} VarIndex componentBefore() const {return mComponentBefore;} /// Returns the number of rows in the grading vector. size_t gradingCount() const { return varCount() == 0 ? 0 : mGradings.size() / varCount(); } /// Returns the grading matrix in row-major layout. const Gradings& gradings() const {return mGradings;} /// Returns true if the grading matrix is a single row of 1's. bool isTotalDegree() const { if (varCount() == 0 || mGradings.size() != varCount()) return false; for (VarIndex var = 0; var < varCount(); ++var) if (mGradings[var] != 1) return false; return true; } BaseOrder baseOrder() const {return mBaseOrder;} bool hasFromLeftBaseOrder() const { return baseOrder() == LexBaseOrderFromLeft || baseOrder() == RevLexBaseOrderFromLeft; } bool hasLexBaseOrder() const { return baseOrder() == LexBaseOrderFromLeft || baseOrder() == LexBaseOrderFromRight; } /// Returns true if the order is a monomial order. A monomial order /// is a total order on monomials where a>b => ac>bc for all /// monomials a,b,c and where the order is a well order. Only the /// well order property could currently fail. It is equivalent to /// stating that x>1 for all variables x. bool isMonomialOrder() const { for (VarIndex var = 0; var < varCount(); ++var) { // Check that x_var > 1. for (size_t grading = 0; ; ++grading) { if (grading == gradingCount()) { // The column was entirely zero, so x_var > 1 if and only if the // base ordering is lex. if (!hasLexBaseOrder()) return false; break; } const auto index = grading * varCount() + var; MATHICGB_ASSERT(index < mGradings.size()); if (mGradings[index] != 0) { // We have found the first non-zero weight in this column, // so x_var > 1 if and only if this weight is positive. if (mGradings[index] < 0) return false; break; } } } return true; } bool componentsAscendingDesired() const {return mComponentsAscendingDesired;} bool schreyering() const {return mSchreyering;} private: bool debugAssertValid() { #ifdef MATHICGB_DEBUG MATHICGB_ASSERT(mGradings.size() == gradingCount() * varCount()); MATHICGB_ASSERT( mComponentBefore == ComponentAfterBaseOrder || mComponentBefore <= gradingCount() ); MATHICGB_ASSERT( mBaseOrder == LexBaseOrderFromLeft || mBaseOrder == RevLexBaseOrderFromLeft || mBaseOrder == LexBaseOrderFromRight || mBaseOrder == RevLexBaseOrderFromRight ); #endif return true; } const VarIndex mVarCount; const Gradings mGradings; const BaseOrder mBaseOrder; const size_t mComponentBefore; const bool mSchreyering; const bool mComponentsAscendingDesired; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/MonoProcessor.hpp000077500000000000000000000103511311555162500220220ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MONO_PROCESSOR_GUARD #define MATHICGB_MONO_PROCESSOR_GUARD #include "Basis.hpp" MATHICGB_NAMESPACE_BEGIN /// Does pre- and post-processing of monomials to implement module monomial /// orders not directly supported by the monoid. template class MonoProcessor; template class MonoProcessor { public: typedef M Monoid; typedef typename Monoid::VarIndex VarIndex; typedef typename Monoid::Component Component; typedef typename Monoid::MonoVector MonoVector; typedef typename Monoid::MonoRef MonoRef; typedef typename Monoid::ConstMonoRef ConstMonoRef; typedef typename Monoid::ConstMonoPtr ConstMonoPtr; MonoProcessor( const Monoid& monoid, const bool componentsAscendingDesired, const bool schreyering ): mComponentsAscendingDesired(componentsAscendingDesired), mComponentCount(0), mSchreyering(schreyering), mSchreyerMultipliersMemory(monoid) {} void setComponentsAscendingDesired(bool value) { mComponentsAscendingDesired = value; } bool componentsAscendingDesired() const {return mComponentsAscendingDesired;} void setSchreyering(bool value) {mSchreyering = true;} bool schreyering() const {return mSchreyering;} void setSchreyerMultipliers(const Basis& basis) { MonoVector schreyer(monoid()); for (size_t gen = 0; gen < basis.size(); ++gen) schreyer.push_back(basis.getPoly(gen)->leadMono()); setSchreyerMultipliers(std::move(schreyer)); } void setSchreyerMultipliers(MonoVector&& moduleAdjustments) { MATHICGB_ASSERT(moduleAdjustments.monoid() == monoid()); MATHICGB_ASSERT(mSchreyerMultipliersMemory.empty() || mSchreyerMultipliersMemory.size() == componentCount()); mSchreyerMultipliersMemory = std::move(moduleAdjustments); mSchreyerMultipliers.clear(); for ( auto it = mSchreyerMultipliersMemory.begin(); it != mSchreyerMultipliersMemory.end(); ++it ) { // in the absence of a separate monoid for (non-module) monomials, // at least we can check that the component is zero. MATHICGB_ASSERT(this->monoid().component(*it) == 0); // todo: there should be a better way of indexing into a // MonoVector. mSchreyerMultipliers.emplace_back((*it).ptr()); } } void preprocess(MonoRef mono) const { if (hasSchreyerMultipliers()) monoid().multiplyInPlace(moduleAdjustment(mono), mono); if (needToReverseComponents()) reverseComponent(mono); } void postprocess(MonoRef mono) const { if (needToReverseComponents()) reverseComponent(mono); if (hasSchreyerMultipliers()) { MATHICGB_ASSERT(monoid().divides(moduleAdjustment(mono), mono)); monoid().divideInPlace(moduleAdjustment(mono), mono); } } bool processingNeeded() const { return needToReverseComponents() || hasSchreyerMultipliers(); } bool needToReverseComponents() const { return Monoid::HasComponent && componentsAscendingDesired() != monoid().componentsAscending(); } bool hasSchreyerMultipliers() const { return !mSchreyerMultipliers.empty(); } void setComponentCount(Component count) {mComponentCount = count;} Component componentCount() const {return mComponentCount;} const Monoid& monoid() const {return mSchreyerMultipliersMemory.monoid();} private: void operator==(const MonoProcessor&) const; // not available void reverseComponent(MonoRef mono) const { const auto component = monoid().component(mono); const auto newComponent = mComponentCount - 1 - component; monoid().setComponent(newComponent, mono); } ConstMonoRef moduleAdjustment(ConstMonoRef mono) const { MATHICGB_ASSERT(hasSchreyerMultipliers()); const auto component = monoid().component(mono); MATHICGB_ASSERT(component < componentCount()); MATHICGB_ASSERT(mSchreyerMultipliers.size() == componentCount()); return *mSchreyerMultipliers[component]; } bool mOrderFromLeft; bool mComponentsAscendingDesired; Component mComponentCount; bool mSchreyering; MonoVector mSchreyerMultipliersMemory; std::vector mSchreyerMultipliers; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/MonomialMap.hpp000077500000000000000000000222301311555162500214220ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_MONOMIAL_MAP_GUARD #define MATHICGB_MONOMIAL_MAP_GUARD #include "FixedSizeMonomialMap.h" #include "mtbb.hpp" #include "Atomic.hpp" #include "PolyRing.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// A concurrent hash map from monomials to T. This map can resize itself /// if there are too few buckets compared to entries. /// /// Queries are supported through a MonomialMap::Reader object. On resize all /// previous readers are subject to permanent spurious misses - /// querying clients need to grab a fresh reader to confirm misses. Grabbing /// a reader incurs synchronization so do not do it for every query. /// /// External synchronization with writers is required if spurious misses are /// not acceptable. There are no spurious hits. If misses are very rare then /// reads can be done with minimal overhead by following this pattern: /// /// 1) grab a reader X /// 2) perform queries on X until done or there is a miss /// 3) replace X with a fresh reader /// 4) go to 2 if the miss is now a hit /// 5) grab a lock shared with all writers /// 6) perform the query again - a miss is now guaranteed to be accurate /// 7) release the lock after the processing of the miss is done and go to 2 /// /// There is no way to avoid locking if spurious misses are not acceptable /// as otherwise a writer could make an insertion of the requested key at any /// time while processing the miss - which then makes the miss spurious /// after-the-fact. template class MonomialMap { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef T mapped_type; typedef FixedSizeMonomialMap FixedSizeMap; typedef typename FixedSizeMap::value_type value_type; MonomialMap(const PolyRing& ring): mMap(new FixedSizeMap(InitialBucketCount, ring)), mCapacityUntilGrowth (maxEntries(mMap.load(std::memory_order_relaxed)->bucketCount())), mRing(ring) { // We can load mMap as std::memory_order_relaxed because we just stored it // and the constructor cannot run concurrently. } ~MonomialMap() { // We can load with std::memory_order_relaxed because the destructor // cannot run concurrently. delete mMap.load(std::memory_order_relaxed); } const PolyRing& ring() const {return mRing;} /// All queries are performed through a Reader. Readers are subject to /// permanent spurious misses on hash map resize. Grab a fresh reader /// on misses to confirm them. Making a Reader imposes synchronization /// overhead. External locking is required to guarantee that a miss is /// genuine since there is no mutual exclusion between queries and /// insertions. /// /// It is intentional that a reader does not have an update() method. The /// purpose of this is to make the internal hash table pointer const inside /// the class which guarantees to the compiler that it will never change. /// This in turn allows the compiler to store the fields of the internal /// hash table pointer such as the hash map mask. If there were an update() /// method this would not be possible and the compiler might have to load /// that mask for every query. I made it this way because I was seeming /// a performance regression of several percent which then went away with /// this solution. (well actually it's a reference, which has the same /// effect). class Reader { public: Reader(const MonomialMap& map): mMap(*map.mMap.load(std::memory_order_seq_cst)) { // We grab the hash table pointer with std::memory_order_seq_cst in order // to force a CPU cache flush - in this way we are more likely to get an // up to date value. } /// Returns the value that mono maps to or null if no such key has been /// inserted. Also returns the internal monomial that matches mono if such /// a monomial exists. Misses can be spurious! Read the comments on the parent /// class. std::pair find(ConstMonoRef mono) const { return mMap.find(mono); } // As find but looks for the product of a and b and also returns the // monomal that is the product. std::pair findProduct( ConstMonoRef a, ConstMonoRef b ) const { return mMap.findProduct(a, b); } /// As findProduct() but looks for the two products a1*b and a2*b /// simultaneously. The purpose of this is similar to that of unrolling a /// loop. MATHICGB_INLINE std::pair findTwoProducts( const ConstMonoRef a1, const ConstMonoRef a2, const ConstMonoRef b ) const { return mMap.findTwoProducts(a1, a2, b); } typedef typename FixedSizeMonomialMap::const_iterator const_iterator; /// The range [begin(), end()) contains all entries in the hash table. /// Insertions invalidate all iterators. Beware that insertions can /// happen concurrently. const_iterator begin() const {return mMap.begin();} const_iterator end() const {return mMap.end();} private: const FixedSizeMonomialMap& mMap; }; /// Removes all entries from the hash table. This requires mutual exclusion /// from and synchronization with all readers and writers. void clearNonConcurrent() { // We can load with std::memory_order_relaxed because this method // requires external synchronization. mMap.load(std::memory_order_relaxed)->clearNonConcurrent(); } /// Makes value.first map to value.second unless value.first is already /// present in the map - in that case nothing is done. If p is the returned /// pair then *p.first.first is the value that value.first maps to after the insert /// and p.second is true if an insertion was performed. *p.first.first will not /// equal value.second if an insertion was not performed - unless the /// inserted value equals the already present value. p.first.second is an /// internal monomial that equals value.first. std::pair, bool> insert(const value_type& value) { const mgb::mtbb::mutex::scoped_lock lockGuard(mInsertionMutex); // We can load mMap as std::memory_order_relaxed because we have already // synchronized with all other mutators by locking mInsertionMutex; auto map = mMap.load(std::memory_order_relaxed); // this is a loop since it is possible to set the growth factor and // the initial size so low that several rounds are required. This should // only happen when debugging as otherwise such low parameters are // not a good idea. while (mCapacityUntilGrowth == 0) { // Resize the table by making a bigger one and using that instead. if (map->bucketCount() > // check overflow std::numeric_limits::max() / GrowthFactor) { throw std::bad_alloc(); } const size_t newBucketCount = map->bucketCount() * GrowthFactor; auto nextMap = make_unique(newBucketCount, std::move(*map)); mOldMaps.emplace_back(map); mCapacityUntilGrowth = maxEntries(nextMap->bucketCount()) - maxEntries(map->bucketCount()); // Store with std::memory_order_seq_cst to force a memory flush so that // readers see the new table as soon as possible. map = nextMap.release(); mMap.store(map, std::memory_order_seq_cst); } MATHICGB_ASSERT(mCapacityUntilGrowth > 0); auto p = map->insert(value); if (p.second) --mCapacityUntilGrowth; return p; } /// Return the number of entries. This method uses internal synchronization /// so do not call too much or you'll get degraded performance. size_t entryCount() const { const mgb::mtbb::mutex::scoped_lock lockGuard(mInsertionMutex); // We can load with std::memory_order_relaxed because we are holding the // lock. auto& map = *mMap.load(std::memory_order_relaxed); return maxEntries(map.bucketCount()) - mCapacityUntilGrowth; } private: static const size_t MinBucketsPerEntry = 3; // inverse of max load factor static const size_t GrowthFactor = 2; static const size_t InitialBucketCount = 1 << 1; static size_t maxEntries(const size_t bucketCount) { return (bucketCount + (MinBucketsPerEntry - 1)) / MinBucketsPerEntry; } Atomic mMap; const PolyRing& mRing; mutable mgb::mtbb::mutex mInsertionMutex; /// Only access this field while holding the mInsertionMutex lock. size_t mCapacityUntilGrowth; /// Only access this field while holding the mInsertionMutex lock. /// Contains the old hash tables that we discarded on resize. We have to /// keep these around as we have no way to determine if there are still /// readers looking at them. This could be changed at the cost of /// more overhead in the Reader constructor and destructor. std::vector> mOldMaps; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/NonCopyable.hpp000077500000000000000000000015061311555162500214250ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_NON_COPYABLE_GUARD #define MATHICGB_NON_COPYABLE_GUARD MATHICGB_NAMESPACE_BEGIN /// Derive from this class to disable the compiler-generated copy /// constructor and assignment. T should be the class that is deriving /// from NonCopyable. /// /// The purpose of the template parameter is to avoid any chance of /// getting a diamond-graph inheritance graph. Diamond graphs can lead /// to runtime overhead. template class NonCopyable { public: NonCopyable() {} NonCopyable(NonCopyable&&) {} // still movable. private: NonCopyable(const NonCopyable&); // unavailable void operator=(const NonCopyable&); // unavailable }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/Poly.hpp000077500000000000000000000212521311555162500201370ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_POLY_GUARD #define MATHICGB_POLY_GUARD #include "PolyRing.hpp" #include "Range.hpp" #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// Stores a polynomial. class Poly { public: typedef PolyRing::Field Field; typedef Field::Element Coef; typedef Field::ConstElementRef ConstCoefRef; typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; /// Constructs the zero polynomial in the given ring. Poly(const PolyRing& ring): mRing(ring), mMonos(ring.monoid()) {} Poly(const Poly& poly): mRing(poly.ring()), mCoefs(poly.mCoefs), mMonos(poly.mMonos) {} Poly(const Poly&& poly): mRing(poly.ring()), mCoefs(std::move(poly.mCoefs)), mMonos(std::move(poly.mMonos)) {} const PolyRing& ring() const {return mRing;} const Monoid& monoid() const {return ring().monoid();} const Field& field() const {return ring().field();} bool isZero() const {return mCoefs.empty();} size_t termCount() const {return mCoefs.size();} size_t getMemoryUse() const { return sizeof(mCoefs.front()) * mCoefs.capacity() + mMonos.memoryBytesUsed(); } /// Returns a polynomial whose terms have been permuted to be in /// descending order. /// /// Making the copy is not wasteful, because doing the permutation in-place /// would be require swapping monomials which is slow if they are large. /// The returned object is not copy (return value optimization) and using /// move assignment this code will only create the single copy of a Poly /// p that is necessary to avoid an in-place operation: /// /// p = p.polyWithTermsDescending() Poly polyWithTermsDescending() { // *** Sort terms in descending order of monomial. // It would be possible but cumbersome to implement a sort directly // on mMonos. That way no allocation would need to happen, however // it is not clear that that would be any faster, since swapping around // monomials in-place is slow. Swapping terms is faster, since terms // just refer to the monomials. This way is also easier to implement. // /// @todo: make a separate TermSorter object that allows the temporary /// vector to be reused between sorts. This should matter for sorting input /// ideals where there might be a lot of polynomials to go through. auto greaterOrEqual = [&](const NewConstTerm& a, const NewConstTerm& b) { return monoid().lessThan(*b.mono, *a.mono); }; auto terms = rangeToVector(*this); std::sort(std::begin(terms), std::end(terms), greaterOrEqual); // *** Make a new polynomial with terms in that order Poly poly(ring()); poly.reserve(termCount()); poly.append(terms); MATHICGB_ASSERT(poly.termsAreInDescendingOrder()); MATHICGB_ASSERT(poly.termCount() == termCount()); return poly; } /// Appends the given term as the last term in the polynomial. void append(ConstCoefRef coef, ConstMonoRef mono) { mCoefs.push_back(coef); mMonos.push_back(mono); } /// Appends the given term as the last term in the polynomial. void append(const NewConstTerm& term) { MATHICGB_ASSERT(term.mono != nullptr); append(term.coef, *term.mono); } /// Appends each term in the range r to the end of the polynomial. template void append(const Range& r) { for (const auto& term : r) append(term); } /// As append(range(termsBegin, termsEnd)) template void append( const ForwardIterator& termsBegin, const ForwardIterator& termsEnd ) { append(range(termsBegin, termsEnd)); } /// Hint that space for the give number of terms is going to be needed. /// This serves the same purpose as std::vector<>::reserve. void reserve(size_t spaceForThisManyTerms) { mMonos.reserve(spaceForThisManyTerms * monoid().entryCount()); } /// Makes the polynomial monic by multiplying by the multiplicative inverse /// of leadCoef(). Calling this method is an error if isZero(). void makeMonic() { MATHICGB_ASSERT(!isZero()); if (isMonic()) return; auto multiplier = field().inverse(leadCoef()); for (auto& coef : mCoefs) coef = field().product(coef, multiplier); MATHICGB_ASSERT(isMonic()); } void setToZero() { mCoefs.clear(); mMonos.clear(); } Poly& operator=(const Poly& poly) {return *this = Poly(poly);} Poly& operator=(Poly&& poly) { MATHICGB_ASSERT(&ring() == &poly.ring()); mCoefs = std::move(poly.mCoefs); mMonos = std::move(poly.mMonos); return *this; } // *** Accessing the coefficients of the terms in the polynomial. /// Returns the coefficient of the leading term. const Coef& leadCoef() const { MATHICGB_ASSERT(!isZero()); return mCoefs.front(); } /// Returns true if the polynomial is monic. A polynomial is monic if /// the coefficient of the leading monomial is 1. If you are asking this /// question about a polynomial, that likely means that you are expecting /// the polynomial not to be zero. So it is an error to ask if the zero /// polynomial is monic - you'll get an assert to help pinpoint the error. bool isMonic() const { MATHICGB_ASSERT(!isZero()); return field().isOne(leadCoef()); } typedef Field::ElementVector CoefVector; typedef CoefVector::const_iterator ConstCoefIterator; typedef Range ConstCoefIteratorRange; ConstCoefIterator coefBegin() const {return mCoefs.begin();} ConstCoefIterator coefEnd() const {return mCoefs.end();} ConstCoefIteratorRange coefRange() const { return range(coefBegin(), coefEnd()); } // *** Accessing the monomials of the terms in the polynomial /// Returns the monomial of the leading term. ConstMonoRef leadMono() const { MATHICGB_ASSERT(!isZero()); return mMonos.front(); } /// Returns the monomial of the last term. ConstMonoRef backMono() const { MATHICGB_ASSERT(!isZero()); return mMonos.back(); } /// Returns true if the terms are in descending order. The terms are in /// descending order when mono(0) >= mono(1) >= ... >= backMono. /// The coefficient of the terms are not considered in this comparison. bool termsAreInDescendingOrder() const { auto greaterThanOrEqual = [&](ConstMonoRef a, ConstMonoRef b) { return !monoid().lessThan(a, b); }; return std::is_sorted(monoBegin(), monoEnd(), greaterThanOrEqual); } typedef Monoid::MonoVector MonoVector; typedef MonoVector::const_iterator ConstMonoIterator; typedef Range ConstMonoIteratorRange; ConstMonoIterator monoBegin() const {return mMonos.begin();} ConstMonoIterator monoEnd() const {return mMonos.end();} ConstMonoIteratorRange monoRange() const { return range(monoBegin(), monoEnd()); } // *** Iteration through terms class ConstTermIterator { public: typedef std::forward_iterator_tag iterator_category; typedef NewConstTerm value_type; typedef ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; ConstTermIterator() {} ConstTermIterator& operator++() { ++mIt; return *this; } value_type operator*() const { auto pair = *mIt; NewConstTerm term = {pair.first, pair.second}; return term; } bool operator==(const ConstTermIterator& it) const {return mIt == it.mIt;} bool operator!=(const ConstTermIterator& it) const {return mIt != it.mIt;} const Coef& coef() const {return (*mIt).first;} ConstMonoRef mono() const {return (*mIt).second;} private: friend class Poly; typedef Zip Iterator; ConstTermIterator(const Iterator& it): mIt(it) {} Iterator mIt; }; typedef Range ConstTermIteratorRange; ConstTermIterator begin() const {return makeZip(coefBegin(), monoBegin());} ConstTermIterator end() const {return makeZip(coefEnd(), monoEnd());} ConstTermIteratorRange termRange() const {return range(begin(), end());} NewConstTerm leadTerm() const { MATHICGB_ASSERT(!isZero()); NewConstTerm term = {leadCoef(), leadMono().ptr()}; return term; } private: friend bool operator==(const Poly &a, const Poly &b); const PolyRing& mRing; CoefVector mCoefs; MonoVector mMonos; }; inline bool operator==(const Poly& a, const Poly& b) { MATHICGB_ASSERT(a.ring() == b.ring()); return a.mCoefs == b.mCoefs && a.mMonos == b.mMonos; } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/PolyBasis.cpp000077500000000000000000000125511311555162500211160ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "PolyBasis.hpp" #include "Basis.hpp" MATHICGB_NAMESPACE_BEGIN PolyBasis::PolyBasis( const PolyRing& ring, std::unique_ptr monoLookup ): mRing(ring), mMonoLookup(std::move(monoLookup)) { MATHICGB_ASSERT(mMonoLookup.get() != 0); mMonoLookup->setBasis(*this); } PolyBasis::~PolyBasis() { EntryIter const stop = mEntries.end(); for (EntryIter it = mEntries.begin(); it != stop; ++it) { if (it->retired) continue; MATHICGB_ASSERT(it->poly != 0); delete it->poly; } } std::unique_ptr PolyBasis::initialIdeal() const { std::unique_ptr basis(new Basis(mRing)); size_t const basisSize = size(); for (size_t gen = 0; gen != basisSize; ++gen) { if (!retired(gen) && leadMinimal(gen)) { std::unique_ptr p(new Poly(mRing)); p->append(1, leadMono(gen)); basis->insert(std::move(p)); } } basis->sort(); return basis; } void PolyBasis::insert(std::unique_ptr poly) { MATHICGB_ASSERT(poly.get() != 0); MATHICGB_ASSERT(!poly->isZero()); poly->makeMonic(); const size_t index = size(); EntryIter const stop = mEntries.end(); const auto lead = poly->leadMono(); #ifdef DEBUG // lead monomials must be unique among basis elements for (EntryIter it = mEntries.begin(); it != stop; ++it) { if (it->retired) continue; MATHICGB_ASSERT(!monoid().equal(lead, it->poly->leadMono())); } #endif // Update information about minimal lead terms. const bool leadMinimal = (divisor(lead) == static_cast(-1)); if (leadMinimal) { class MultipleOutput : public MonoLookup::EntryOutput { public: MultipleOutput(EntryCont& entries): mEntries(entries) {} virtual bool proceed(size_t index) { MATHICGB_ASSERT(index < mEntries.size()); mEntries[index].leadMinimal = false; return true; } private: EntryCont& mEntries; }; MultipleOutput out(mEntries); monoLookup().multiples(lead, out); } mMonoLookup->insert(lead, index); mEntries.push_back(Entry()); Entry& entry = mEntries.back(); entry.poly = poly.release(); entry.leadMinimal = leadMinimal; MATHICGB_ASSERT(mEntries.back().poly != 0); } std::unique_ptr PolyBasis::retire(size_t index) { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); mMonoLookup->remove(leadMono(index)); std::unique_ptr poly(mEntries[index].poly); mEntries[index].poly = 0; mEntries[index].retired = true; return poly; } std::unique_ptr PolyBasis::toBasisAndRetireAll() { auto basis = make_unique(ring()); for (size_t i = 0; i < size(); ++i) if (!retired(i)) basis->insert(retire(i)); return basis; } size_t PolyBasis::divisor(ConstMonoRef mono) const { size_t index = monoLookup().divisor(mono); MATHICGB_ASSERT((index == static_cast(-1)) == (divisorSlow(mono) == static_cast(-1))); MATHICGB_ASSERT(index == static_cast(-1) || monoid().divides(leadMono(index), mono)); return index; } size_t PolyBasis::classicReducer(ConstMonoRef mono) const { const auto index = monoLookup().classicReducer(mono); MATHICGB_ASSERT((index == static_cast(-1)) == (divisorSlow(mono) == static_cast(-1))); MATHICGB_ASSERT(index == static_cast(-1) || monoid().divides(leadMono(index), mono)); return index; } size_t PolyBasis::divisorSlow(ConstMonoRef mono) const { const size_t stop = size(); for (size_t i = 0; i != stop; ++i) if (!retired(i) && monoid().dividesWithComponent(leadMono(i), mono)) return i; return static_cast(-1); } bool PolyBasis::leadMinimalSlow(size_t index) const { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); const auto lead = leadMono(index); EntryCIter const skip = mEntries.begin() + index; EntryCIter const stop = mEntries.end(); for (EntryCIter it = mEntries.begin(); it != stop; ++it) { if (it->retired) continue; const auto itLead = it->poly->leadMono(); if (monoid().divides(itLead, lead) && it != skip) return false; } return true; } size_t PolyBasis::minimalLeadCount() const { // todo: use iterators size_t minCount = 0; const size_t stop = size(); for (size_t i = 0; i != stop; ++i) if (!retired(i) && leadMinimal(i)) ++minCount; return minCount; } size_t PolyBasis::maxIndexMinimalLead() const { // todo: use iterators size_t i = size() - 1; for (; i != static_cast(-1); --i) if (!retired(i) && leadMinimal(i)) break; return i; } size_t PolyBasis::monomialCount() const { size_t sum = 0; EntryCIter const stop = mEntries.end(); for (EntryCIter it = mEntries.begin(); it != stop; ++it) if (!it->retired) sum += it->poly->termCount(); return sum; } size_t PolyBasis::getMemoryUse() const { size_t sum = mEntries.capacity() * sizeof(mEntries.front()); EntryCIter const stop = mEntries.end(); for (EntryCIter it = mEntries.begin(); it != stop; ++it) if (!it->retired) sum += it->poly->getMemoryUse(); return sum; } PolyBasis::Entry::Entry(): poly(0), leadMinimal(0), retired(false), usedAsStartCount(0), usedAsReducerCount(0), possibleReducerCount(0), nonSignatureReducerCount(0) {} MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/PolyBasis.hpp000077500000000000000000000167311311555162500211270ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_POLY_BASIS_GUARD #define MATHICGB_POLY_BASIS_GUARD #include "Poly.hpp" #include "MonoLookup.hpp" #include #include MATHICGB_NAMESPACE_BEGIN class PolyRing; class Basis; /// Stores a basis of polynomials. Designed for use in Groebner basis /// algorithms. class PolyBasis { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; PolyBasis( const PolyRing& ring, std::unique_ptr monoLookup ); ~PolyBasis(); /// Returns a basis of the initial ideal. std::unique_ptr initialIdeal() const; /// Inserts a polynomial into the basis at index size() - or index size() - 1 /// after calling, since size() will increase by one. /// Lead monomials must be unique among basis elements. void insert(std::unique_ptr poly); /// Returns the index of a basis element whose lead term divides mon. /// Returns -1 if there is no such basis element. size_t divisor(ConstMonoRef mon) const; /// As divisor(mon), but if there is more than one divisor then the divisor /// is chosen according to some notion of which reducer is better. size_t classicReducer(ConstMonoRef mon) const; /// Replaces basis element at index with the given new polynomial. The lead /// term of the new polynomial must be the same as the previous one. /// This is useful for auto-tail-reduction. void replaceSameLeadTerm(size_t index, std::unique_ptr newValue) { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); MATHICGB_ASSERT(newValue.get() != nullptr); MATHICGB_ASSERT(!newValue->isZero()); MATHICGB_ASSERT (monoid().equal(leadMono(index), newValue->leadMono())); mMonoLookup->remove(leadMono(index)); delete mEntries[index].poly; mEntries[index].poly = newValue.release(); mMonoLookup->insert(leadMono(index), index); MATHICGB_ASSERT(mEntries[index].poly != nullptr); } /// Returns the number of basis elements, including retired elements. size_t size() const {return mEntries.size();} const PolyRing& ring() const {return mRing;} const Monoid& monoid() const {return ring().monoid();} /// Returns a data structure containing the lead monomial of each basis /// element. const MonoLookup& monoLookup() const {return *mMonoLookup;} /// Retires the basis element at index, which returns ownership of the /// polynomial to the caller and frees most resources associated to /// that basis elements. std::unique_ptr retire(size_t index); /// Returns an basis containing all non-retired basis elements and /// retires all those basis elements. The point of the simultaneous /// retirement is that this way no polynomials need be copied. std::unique_ptr toBasisAndRetireAll(); /// Returns true if the basis element at index has been retired. bool retired(size_t index) const { MATHICGB_ASSERT(index < size()); return mEntries[index].retired; } /// Returns the basis element polynomial at index. Poly& poly(size_t index) { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); return *mEntries[index].poly; } /// Returns the basis element polynomial at index. const Poly& poly(size_t index) const { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); return *mEntries[index].poly; } /// Returns the lead monomial of poly(index). ConstMonoRef leadMono(size_t index) const { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); return poly(index).leadMono(); } /// Returns the lead coefficient of poly(index). coefficient leadCoef(size_t index) const { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); return poly(index).leadCoef(); } /// Returns true if the leading monomial of the basis element at index is not /// divisible by the lead monomial of any other basis element. Lead /// monomials are required to be unique among basis elements, so the case /// of several equal lead monomials does not occur. bool leadMinimal(size_t index) const { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); MATHICGB_SLOW_ASSERT(mEntries[index].leadMinimal == leadMinimalSlow(index)); return mEntries[index].leadMinimal; } /// Returns true if the lead monomial of poly is not divisible by the /// lead monomial of any basis element. Equality counts as divisibility. bool leadMinimal(const Poly& poly) const { MATHICGB_ASSERT(&poly != 0); return mMonoLookup->divisor(poly.leadMono()) != static_cast(-1); } /// Returns the number of basis elements with minimal lead monomial. size_t minimalLeadCount() const; /// Returns the index of the basis element of maximal index /// whose lead monomial is minimal. size_t maxIndexMinimalLead() const; /// Returns the basis element polynomial at index. const Poly& basisElement(size_t index) const { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); return *mEntries[index].poly; } /// Returns the number of monomials across all the basis elements. /// Monomials that appear in more than one basis element are counted more /// than once. size_t monomialCount() const; /// Returns how many bytes has been allocated by this object. size_t getMemoryUse() const; void usedAsStart(size_t index) const { MATHICGB_ASSERT(index < size()); ++mEntries[index].usedAsStartCount; } unsigned long long usedAsStartCount(size_t index) const { MATHICGB_ASSERT(index < size()); return mEntries[index].usedAsStartCount; } void usedAsReducer(size_t index) const { MATHICGB_ASSERT(index < size()); ++mEntries[index].usedAsReducerCount; } unsigned long long usedAsReducerCount(size_t index) const { MATHICGB_ASSERT(index < size()); return mEntries[index].usedAsReducerCount; } void wasPossibleReducer(size_t index) const { MATHICGB_ASSERT(index < size()); ++mEntries[index].possibleReducerCount; } unsigned long long wasPossibleReducerCount(size_t index) const { MATHICGB_ASSERT(index < size()); return mEntries[index].possibleReducerCount; } void wasNonSignatureReducer(size_t index) const { MATHICGB_ASSERT(index < size()); ++mEntries[index].nonSignatureReducerCount; } unsigned long long wasNonSignatureReducerCount(size_t index) const { MATHICGB_ASSERT(index < size()); return mEntries[index].nonSignatureReducerCount; } private: // Slow versions use simpler code. Used to check results in debug mode. bool leadMinimalSlow(size_t index) const; size_t divisorSlow(ConstMonoRef mon) const; class Entry { public: Entry(); Poly* poly; bool leadMinimal; bool retired; // Statistics on reducer choice in reduction mutable unsigned long long usedAsStartCount; mutable unsigned long long usedAsReducerCount; mutable unsigned long long possibleReducerCount; mutable unsigned long long nonSignatureReducerCount; }; typedef std::vector EntryCont; typedef EntryCont::iterator EntryIter; typedef EntryCont::const_iterator EntryCIter; const PolyRing& mRing; std::unique_ptr mMonoLookup; std::vector mEntries; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/PolyHashTable.cpp000077500000000000000000000044421311555162500217100ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "PolyHashTable.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN PolyHashTable::PolyHashTable(const PolyRing& ring): mHashToIndexMask(computeHashMask(1000)), mBuckets (make_unique_array(hashMaskToBucketCount(mHashToIndexMask))), mRing(ring), mNodes(sizeofNode(ring) ), mSize() { mMaxSize = static_cast(bucketCount() * maxLoadFactor()); std::fill_n(mBuckets.get(), bucketCount(), nullptr); } void PolyHashTable::rehash(const size_t requestedBucketCount) { const auto newHashToIndexMask = computeHashMask(requestedBucketCount); const auto newBucketCount = hashMaskToBucketCount(newHashToIndexMask); auto newBuckets = make_unique_array(newBucketCount); std::fill_n(newBuckets.get(), newBucketCount, nullptr); const auto bucketsEnd = mBuckets.get() + bucketCount(); for (auto bucket = mBuckets.get(); bucket != bucketsEnd; ++bucket) { for (auto node = *bucket; node != 0;) { const auto hash = monoid().hash(node->mono()); const auto newIndex = hashToIndex(hash, newHashToIndexMask); const auto next = node->next(); node->next() = newBuckets[newIndex]; newBuckets[newIndex] = node; node = next; } } mHashToIndexMask = newHashToIndexMask; mBuckets = std::move(newBuckets); mMaxSize = static_cast(bucketCount() * maxLoadFactor()); } HashValue PolyHashTable::computeHashMask(const size_t requestedBucketCount) { // round request up to nearest power of 2. size_t pow2 = 1; while (pow2 < requestedBucketCount && 2 * pow2 != 0) pow2 *= 2; MATHICGB_ASSERT(pow2 > 0 && (pow2 & (pow2 - 1)) == 0); // power of two // If casting to a hash value overflows, then we get the maximum // possible number of buckets based on the range of the hash // value type. Only unsigned overflow is defined, so we need // to assert that the hash type is unsigned. static_assert(!std::numeric_limits::is_signed, ""); const auto hashToIndexMask = static_cast(pow2 - 1); MATHICGB_ASSERT(pow2 == hashMaskToBucketCount(hashToIndexMask)); return hashToIndexMask; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/PolyHashTable.hpp000077500000000000000000000120561311555162500217150ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_POLY_HASH_TABLE_GUARD #define MATHICGB_POLY_HASH_TABLE_GUARD #include "PolyRing.hpp" #include "Poly.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN class PolyHashTable { public: typedef PolyRing::Monoid Monoid; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoRef MonoRef; typedef coefficient Value; class Node { public: ConstMonoRef mono() const {return *Monoid::toMonoPtr(mMono);} MonoRef mono() {return *Monoid::toMonoPtr(mMono);} Value& value() {return mValue;} const Value& value() const {return mValue;} private: friend class PolyHashTable; Node*& next() {return mNext;} Node* next() const {return mNext;} Node* mNext; Value mValue; exponent mMono[1]; }; // Construct a hash table with at least requestedBucketCount buckets. There // may be more buckets. Currently the number is rounded up to the next power // of two. PolyHashTable(const PolyRing& ring); const PolyRing::Monoid& monoid() const {return mRing.monoid();} /// Return how many buckets the hash table has. size_t bucketCount() const { return hashMaskToBucketCount(mHashToIndexMask); } /// Return the number of elements (not the number of buckets). size_t size() const {return mSize;} MATHICGB_INLINE std::pair insertProduct(ConstMonoRef a, ConstMonoRef b) { auto newNode = new (mNodes.alloc()) Node(); monoid().multiply(a, b, newNode->mono()); const auto abHash = monoid().hash(newNode->mono()); auto& bucket = mBuckets[hashToIndex(abHash)]; for (auto node = bucket; node != nullptr; node = node->next()) { if (abHash != monoid().hash(node->mono())) continue; if (monoid().equal(newNode->mono(), node->mono())) { mNodes.free(newNode); return std::make_pair(node, false); // found a*b. } } mRing.coefficientSet(newNode->value(), 0); newNode->next() = bucket; bucket = newNode; ++mSize; if (mSize >= mMaxSize) rehash(bucketCount() * 2); return std::make_pair(newNode, true); // inserted mono } MATHICGB_INLINE std::pair insertProduct (ConstMonoRef a, ConstMonoRef b, Value add) { auto p = insertProduct(a, b); mRing.coefficientAddTo(p.first->value(), add); return p; } MATHICGB_INLINE std::pair insertProduct(NewConstTerm a, NewConstTerm b) { Value prod; mRing.coefficientMult(a.coef, b.coef, prod); return insertProduct(*a.mono, *b.mono, prod); } MATHICGB_INLINE void remove(Node* nodeToRemove) { MATHICGB_ASSERT(nodeToRemove != 0); MATHICGB_ASSERT(mNodes.fromPool(nodeToRemove)); const auto index = hashToIndex(monoid().hash(nodeToRemove->mono())); auto nodePtr = &mBuckets[index]; while (*nodePtr != nodeToRemove) { MATHICGB_ASSERT(*nodePtr != nullptr); nodePtr = &(*nodePtr)->next(); } *nodePtr = nodeToRemove->next(); mNodes.free(nodeToRemove); --mSize; } /// Removes all elements and optimizes internal resources. This is /// fast if there are no elements, so if you know that there are no /// elements and that many operations have happened since the last clear, /// then call clear for better cache performance. If there is even one /// element, then this takes linear time in the number of buckets. void clear() { if (!empty()) { std::fill_n(mBuckets.get(), bucketCount(), nullptr); mSize = 0; } mNodes.freeAllBuffers(); } bool empty() const {return mSize == 0;} size_t getMemoryUse() const { return bucketCount() * sizeof(mBuckets[0]) + mNodes.getMemoryUse(); } private: /// Change the number of buckets and put all the nodes into their new /// places. The bucket array gets put into new memory, but all the nodes /// stay where they are. void rehash(const size_t requestedBucketCount); static HashValue computeHashMask(const size_t requestedBucketCount); static size_t hashMaskToBucketCount(const HashValue mask) { const auto count = static_cast(mask) + 1u; // should be power of 2 MATHICGB_ASSERT(count > 0 && (count & (count - 1)) == 0); return count; } static size_t sizeofNode(const PolyRing& ring) { return sizeof(Node) + sizeof(Value) - sizeof(exponent) + ring.maxMonomialByteSize(); } /// The maximum allowed value of size() / bucketCount() before a rehash /// is done. static double maxLoadFactor() {return 0.10;} size_t hashToIndex(const HashValue hash) const { const auto index = hashToIndex(hash, mHashToIndexMask); MATHICGB_ASSERT(index == hash % bucketCount()); return index; } static size_t hashToIndex(const HashValue hash, const HashValue mask) { return hash & mask; } HashValue mHashToIndexMask; std::unique_ptr mBuckets; const PolyRing& mRing; memt::BufferPool mNodes; size_t mSize; size_t mMaxSize; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/PolyRing.cpp000077500000000000000000000143411311555162500207530ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "PolyRing.hpp" #include #include #include #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN PolyRing::PolyRing(const Field& field, Monoid&& monoid): mField(field), mMonoid(std::move(monoid)) {} PolyRing::PolyRing( coefficient p0, int nvars, bool lexBaseOrder, std::vector&& weights ): mField(p0), mMonoid( MonoOrder( nvars, std::move(weights), lexBaseOrder ? MonoOrder::LexBaseOrderFromRight : MonoOrder::RevLexBaseOrderFromRight ) ) {} /////////////////////////////////////// // (New) Monomial Routines //////////// /////////////////////////////////////// void PolyRing::setWeightsAndHash(Monomial& a1) const { setWeightsOnly(a1); setHashOnly(a1); } int PolyRing::monomialCompare(ConstMonomial sig, ConstMonomial m2, ConstMonomial sig2) const // returns LT, EQ, or GT, depending on sig ? (m2 * sig2). { return monoid().compare(sig, m2, sig2); } void PolyRing::monomialSetIdentity(Monomial& result) const { monoid().setIdentity(result); } void PolyRing::monomialEi(Monoid::Component i, Monomial &result) const { monoid().setIdentity(result); monoid().setComponent(i, result); } void PolyRing::monomialMultTo(Monomial &a, ConstMonomial b) const { monoid().multiplyInPlace(b, a); } void PolyRing::monomialCopy(ConstMonomial a, Monomial& result) const { monoid().copy(a, result); } void PolyRing::monomialQuotientAndMult(ConstMonomial a, ConstMonomial b, ConstMonomial c, Monomial& result) const { monoid().colonMultiply(b, a, c, result); } void PolyRing::monomialFindSignature(ConstMonomial v1, ConstMonomial v2, ConstMonomial u1, Monomial& t1) const { monoid().colonMultiply(v1, v2, u1, t1); } size_t PolyRing::monomialSizeOfSupport(ConstMonomial m) const { return monoid().sizeOfSupport(m); } void PolyRing::mysteriousSPairMonomialRoutine(ConstMonomial newSig, ConstMonomial newLead, ConstMonomial baseDivSig, ConstMonomial baseDivLead, Monomial result) const { result[0] = 0; // set component for (size_t i = 1; i <= varCount(); ++i) { exponent x = newSig[i] - baseDivSig[i] + baseDivLead[i]; if (newLead[i] <= x) x = std::numeric_limits::max(); result[i] = std::max(baseDivLead[i], x); } } // The following two read/write monomials in the form: // letter number letter number ... letter number < number > // allowed letters: a-zA-Z // also allowed instead of letter: [ number ], [0] refers to first var, etc. // What about errors?? void PolyRing::monomialParse(std::istream &i, Monomial& result) const { // monoid().parseM2(i, result); // first initialize result: for (size_t j=0; j< maxMonomialSize(); j++) result[j] = 0; uint64 e; int v, x; // now look at the next char for (;;) { char next = i.peek(); if (isalpha(next)) { // determine variable v = next - 'a'; if (v > 25 || v < 0) v = next - 'A' + 26; if (v < 0 || v > 51) std::cerr << "variable out of range" << std::endl; i.get(); // move past the letter next = i.peek(); e = 1; if (isdigit(next)) i >> e; result[v+1] = static_cast(e); } else if (next == '<') { // get component i.get(); i >> x; *result = x; // place component if (i.peek() == '>') i.get(); } else { break; // We assume that we are at the end of the monomial } } setWeightsAndHash(result); } void PolyRing::monomialDisplay(std::ostream &o, ConstMonomial a, bool print_comp, bool print_one) const { // We display a monomial in the form that can be used with monomialParse // print_one: only is consulted in print_comp is false. bool printed_any = false; for (size_t i=0; i< varCount(); i++) { if (a[i+1] != 0) { printed_any = true; if (i <= 25) o << static_cast('a' + i); else o << static_cast('A' + (i - 26)); if (a[i+1] != 1) o << static_cast(a[i+1]); } } if (print_comp) o << '<' << static_cast(*a.mValue) << '>'; else if (!printed_any && print_one) o << "1"; } void PolyRing::monomialDisplay(FILE* file, ConstMonomial mono, bool printComponent, bool printOne) const { const unsigned int letterCount = 26; MATHICGB_ASSERT(getNumVars() <= 2 * letterCount); bool printedAny = false; for (size_t var = 0; var < varCount(); ++var) { exponent e = monomialExponent(mono, var); if (e == 0) continue; printedAny = true; char varChar; if (var < letterCount) varChar = static_cast('a' + var); else varChar = static_cast('A' + (var - letterCount)); fputc(varChar, file); if (e != 1) fprintf(file, "%i", e); } if (printComponent) fprintf(file, "<%i>", mono.component()); else if (!printedAny && printOne) fputc('1', file); } void PolyRing::printMonomialFrobbyM2Format(std::ostream& out, ConstMonomial m) const { out << " "; bool isOne = true; for (size_t i = 0; i < varCount(); ++i) { const auto e = m[i + 1]; if (e == 0) continue; if (!isOne) out << '*'; else isOne = false; out << 'x' << (i + 1) << '^' << e; } if (isOne) out << '1'; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/PolyRing.hpp000077500000000000000000000540601311555162500207620ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_POLY_RING_GUARD #define MATHICGB_POLY_RING_GUARD #include "MonoMonoid.hpp" #include "PrimeField.hpp" #include #include #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN #define LT (-1) #define EQ 0 #define GT 1 template PrimeField< typename std::make_unsigned< typename std::remove_reference::type >::type > makeField(T charac) { return charac; } /** Returns a^-1 mod modulus. It is required that 0 < a < modulus. */ template T modularInverse(T a, T modulus) { MATHICGB_ASSERT(0 < a); MATHICGB_ASSERT(a < modulus); auto f = makeField(modulus); return f.inverse(f.toElementInRange(a)).value(); } template struct ModularProdType {}; template<> struct ModularProdType {typedef uint16 type;}; template<> struct ModularProdType {typedef uint32 type;}; template<> struct ModularProdType {typedef uint64 type;}; template<> struct ModularProdType {typedef int16 type;}; template<> struct ModularProdType {typedef int32 type;}; template<> struct ModularProdType {typedef int64 type;}; /** Returns a*b mod modulus. It is required that 0 <= a, b < modulus. */ template T modularProduct(T a, T b, T modulus) { MATHICGB_ASSERT(0 < a); MATHICGB_ASSERT(a < modulus); MATHICGB_ASSERT(0 <= b); MATHICGB_ASSERT(b < modulus); auto f = makeField(modulus); return f.product(f.toElementInRange(a), f.toElementInRange(b)).value(); } /** Returns a+b mod modulus. It is required that 0 <= a, b < modulus. */ template T modularSum(T a, T b, T modulus) { MATHICGB_ASSERT(0 < a); MATHICGB_ASSERT(a < modulus); MATHICGB_ASSERT(0 <= b); MATHICGB_ASSERT(b < modulus); auto f = makeField(modulus); return f.sum(f.toElementInRange(a), f.toElementInRange(b)).value(); } /** Returns -a mod modulus. It is required that 0 <= a < modulus. */ template T modularNegative(T a, T modulus) { MATHICGB_ASSERT(0 < a); MATHICGB_ASSERT(a < modulus); auto f = makeField(modulus); return f.negative(f.toElementInRange(a)).value(); } /** Returns -a mod modulus. It is required that 0 < a < modulus. */ template T modularNegativeNonZero(T a, T modulus) { MATHICGB_ASSERT(0 < a); MATHICGB_ASSERT(a < modulus); auto f = makeField(modulus); return f.negativeNonZero(f.toElementInRange(a)).value(); } typedef int32 exponent ; typedef uint32 HashValue; typedef long coefficient; typedef MonoMonoid Monoid; /// This typedef should really be for an unsigned type. typedef PrimeField Field; typedef exponent* vecmonomial; // includes a component typedef coefficient const_coefficient; #define OLDMON #ifdef OLDMON class Monomial; class ConstMonomial { friend class PolyRing; friend class OrderA; friend class OrderB; friend class OrderC; friend class OrderD; friend class OrderE; public: //* Wrap a raw pointer to create a monomial // Assumptions: // 1. This is done in the presence of a PolyRing // 2. Space for the monomial has been created ConstMonomial() : mValue(0) {} ConstMonomial(const exponent *val) : mValue(val) {} inline const Monomial& castAwayConst() const; bool isNull() const { return mValue == 0; } exponent const * unsafeGetRepresentation() const { return mValue; } exponent component() const { return *mValue; } operator Monoid::ConstMonoRef() const { MATHICGB_ASSERT(!isNull()); return Monoid::toRef(mValue); } operator Monoid::ConstMonoPtr() const { return Monoid::toRef(mValue).ptr(); } private: const exponent& operator[](size_t index) const { return mValue[index]; } const exponent& operator*() const { return *mValue; } protected: exponent const* mValue; }; class Monomial : public ConstMonomial { friend class PolyRing; friend class OrderA; friend class OrderB; friend class OrderC; friend class OrderD; friend class OrderE; public: //* Wrap a raw pointer to create a monomial // Assumptions: // 1. This is done in the presence of a PolyRing // 2. Space for the monomial has been created Monomial() : ConstMonomial() {} Monomial(exponent *val) : ConstMonomial(val) {} void swap(Monomial& monomial) { std::swap(mValue, monomial.mValue); } exponent * unsafeGetRepresentation() { return const_cast(mValue); } exponent const * unsafeGetRepresentation() const { return mValue; } operator Monoid::MonoRef() { MATHICGB_ASSERT(!isNull()); return Monoid::toRef(unsafeGetRepresentation()); } operator Monoid::MonoPtr() { return Monoid::toRef(unsafeGetRepresentation()).ptr(); } private: const exponent& operator[](size_t index) const { return mValue[index]; } exponent& operator[](size_t index) { return unsafeGetRepresentation()[index]; } const exponent& operator*() const { return *mValue; } exponent& operator*() { return * const_cast(mValue); } }; inline const Monomial& ConstMonomial::castAwayConst() const { return reinterpret_cast(*this); } typedef Monomial monomial; typedef ConstMonomial const_monomial; #else typedef MonoMonoid::MonoPtr monomial; typedef MonoMonoid::MonoPtr Monomial; typedef MonoMonoid::ConstMonoPtr const_monomial; typedef MonoMonoid::ConstMonoPtr ConstMonomial; #endif struct NewConstTerm { coefficient coef; MonoMonoid::ConstMonoPtr mono; }; struct NewTerm { coefficient coef; MonoMonoid::MonoPtr mono; operator NewConstTerm() const { NewConstTerm t = {coef, mono}; return t; } }; struct const_term { const_term() {} const_term(const_coefficient c, const_monomial m) : coeff(c), monom(m) {} const_coefficient coeff; const_monomial monom; }; struct term { term() {} term(coefficient c, monomial m) : coeff(c), monom(m) {} coefficient coeff; monomial monom; operator const_term() const {return const_term(coeff, monom);} }; class PolyRing { public: typedef MonoMonoid Monoid; /// This typedef should really be for an unsigned type. typedef PrimeField Field; /// @todo: make this dependent on the monoid and field once all code /// has been migrated from ::term to PolyRing::Term. typedef mgb::term Term; PolyRing( coefficient charac, int nvars, bool lexBaseOrder, std::vector&& weights ); PolyRing(const Field& field, Monoid&& monoid); size_t getMemoryUse() const { // todo: Make this more accurate. return 0; } coefficient charac() const { return mField.charac(); } size_t getNumVars() const { return varCount();} size_t varCount() const {return monoid().varCount();} // Allocate a monomial from an arena A. // This monomial may only be freed if no other elements that were allocated // later are live on A. In this case, use freeMonomial(A,m) to free 'm'. Monomial allocMonomial(memt::Arena &A) const { exponent* ptr = static_cast(A.alloc(maxMonomialByteSize())); #ifdef MATHICGB_DEBUG // fill with value that do not make sense to catch bugs in debug // mode. The maximum value of setting all bits increases the // chances of getting an assert. std::fill_n(reinterpret_cast(ptr), maxMonomialByteSize(), ~static_cast(0)); #endif return ptr; } // Free monomial 'm' obtained by allocMonomial(A) by calling // freeMonomial(A,m) Recall this only works if this was the last // thing allocated in A. void freeTopMonomial(memt::Arena &A, Monomial m) const { A.freeTop(m.unsafeGetRepresentation()); } // Allocate a monomial from a pool that has had its size set to // maxMonomialByteSize() // Free monomials here using the SAME pool Monomial allocMonomial(memt::BufferPool &P) const { exponent* ptr = static_cast(P.alloc()); #ifdef MATHICGB_DEBUG // fill with value that do not make sense to catch bugs in debug // mode. The maximum value of setting all bits increases the // chances of getting an assert. std::fill_n(reinterpret_cast(ptr), maxMonomialByteSize(), ~static_cast(0)); #endif return ptr; } // Free monomial 'm' obtained by allocMonomial(P) // by calling freeMonomial(P,m) void freeMonomial(memt::BufferPool &P, Monomial m) const { P.free(m.unsafeGetRepresentation()); } // Only call this method for monomials returned by allocMonomial(). void freeMonomial(Monomial m) const { monoid().freeRaw(Monoid::MonoPtr(m)); } // Free monomials allocated here by calling freeMonomial(). monomial allocMonomial() const { return Monoid::rawPtr(monoid().alloc().release()); } bool fromPool(ConstMonomial m) const { return monoid().fromPool(m); } coefficient toCoefficient(int64 value) const; coefficient coefficientNegate(coefficient coeff) const; coefficient coefficientNegateNonZero(coefficient coeff) const; coefficient coefficientSubtract(coefficient a, coefficient b) const; void coefficientFromInt(coefficient &result, int a) const; void coefficientSetOne(coefficient &result) const { result = 1; } void coefficientAddOneTo(coefficient &result) const; void coefficientReciprocalTo(coefficient &result) const; void coefficientNegateTo(coefficient &result) const; // result = -result void coefficientAddTo(coefficient &result, coefficient a, coefficient b) const; // result += a*b void coefficientAddTo(coefficient &result, coefficient a) const; // result += a void coefficientMultTo(coefficient &result, coefficient a) const; // result *= a void coefficientMult(coefficient a, coefficient b, coefficient &result) const; // result = a*b void coefficientDivide(coefficient a, coefficient b, coefficient &result) const; // result /= a void coefficientSet(coefficient &result, coefficient a) const { result = a; } bool coefficientIsZero(coefficient a) const { return a == 0; } bool coefficientIsOne(coefficient a) const { return a == 1; } bool coefficientEQ(coefficient a, coefficient b) const { return a == b; } size_t maxMonomialByteSize() const { return maxMonomialSize() * sizeof(exponent); } size_t maxMonomialSize() const { return monoid().entryCount(); } /////////////////////////////////////////// // Monomial Routines ////////////////////// /////////////////////////////////////////// HashValue monomialHashValue(ConstMonomial m) const { return monoid().hash(m); } void monomialSetExponent(Monomial m, size_t var, exponent c) const { monoid().setExponent(var, c, m); } void monomialSetExternalExponents(Monomial m, exponent* exponents) const { monoid().setExternalExponents(exponents, m); } exponent monomialExponent(ConstMonomial m, size_t var) const { return monoid().exponent(m, var); } // This function only sets component and the monomial itself. NOT weights, degree, or hash value //TODO: get Bjarke to name this function!! void mysteriousSPairMonomialRoutine(ConstMonomial newSig, ConstMonomial newLead, ConstMonomial baseDivSig, ConstMonomial baseDivLead, Monomial result) const; // Returns the weight (degree) of a. Takes the first weight if // working with several weight vectors. exponent weight(ConstMonomial a) const; void setWeightsAndHash(Monomial& a) const; inline void setWeightsOnly(Monomial& a) const; inline void setHashOnly(Monomial& a) const; // returns LT, EQ, or GT, depending on sig ? (m2 * sig2). int monomialCompare(ConstMonomial a, ConstMonomial b) const; // returns LT, EQ or GT int monomialCompare(ConstMonomial sig, ConstMonomial m2, ConstMonomial sig2) const; // If this method returns true for monomials a and b then it is guaranteed // the multiplying a and b together will not overflow the underlying // exponent integer. Does not work for negative exponents. bool monomialHasAmpleCapacity(ConstMonomial mono) const; bool monomialLT(ConstMonomial a, ConstMonomial b) const { return monoid().lessThan(a, b); } bool monomialEQ(ConstMonomial a, ConstMonomial b) const; /// as monomialEQ, but optimized for the case that the answer is true. bool monomialEqualHintTrue(ConstMonomial a, ConstMonomial b) const; exponent monomialGetComponent(ConstMonomial a) const { return *a.mValue; } void monomialChangeComponent(Monomial a, int x) const { monoid().setComponent(x, a); } void monomialSetIdentity(Monomial& result) const; void monomialEi(Monoid::Component i, Monomial &result) const; void monomialMult(ConstMonomial a, ConstMonomial b, Monomial &result) const; void monomialMultTo(Monomial &a, ConstMonomial b) const; // a *= b /// Result is set to b/a. a must divide b. void monomialDivide(ConstMonomial a, ConstMonomial b, Monomial &result) const; /// sets result to a/b, even if that produces negative exponents. void monomialDivideToNegative(ConstMonomial a, ConstMonomial b, Monomial &result) const; /// Sets aColonB = a:b and bColonA = b:a. void monomialColons(ConstMonomial a, ConstMonomial b, monomial aColonB, monomial bColonA) const; /// returns true if b divides a. Components are ignored. bool monomialIsDivisibleBy(ConstMonomial a, ConstMonomial b) const; /// Returns true if ab is the product of a and b. bool monomialIsProductOf (ConstMonomial a, ConstMonomial b, ConstMonomial ab) const; /// As monomialIsProductOf but optimized for the case that the result /// is true. bool monomialIsProductOfHintTrue (ConstMonomial a, ConstMonomial b, ConstMonomial ab) const; /// As monomialIsProductOfHintTwo(), but checks two products are equal. /// The return value is true if a1*b = a1b and a2*b = a2b. MATHICGB_INLINE bool monomialIsTwoProductsOfHintTrue( ConstMonomial a1, ConstMonomial a2, ConstMonomial b, ConstMonomial a1b, ConstMonomial a2b) const; /// Returns the hash of the product of a and b. HashValue monomialHashOfProduct(ConstMonomial a, ConstMonomial b) const { return monoid().hashOfProduct(a, b); } void monomialCopy(ConstMonomial a, Monomial &result) const; void monomialQuotientAndMult(ConstMonomial a, ConstMonomial b, ConstMonomial c, Monomial& result) const; // result is set to (a//b) * c inline bool monomialRelativelyPrime(ConstMonomial a, ConstMonomial b) const; void monomialFindSignature(ConstMonomial v1, ConstMonomial v2, ConstMonomial u1, Monomial& t1) const; // answer into the already allocated t1 size_t monomialSizeOfSupport(ConstMonomial m) const; inline void monomialLeastCommonMultiple(ConstMonomial a, ConstMonomial b, Monomial& l) const; bool monomialIsLeastCommonMultiple(ConstMonomial a, ConstMonomial b, ConstMonomial l) const; // Returns true if there is a variable var such that hasLarger raises var to // a strictly greater exponent than both smaller1 and smaller2 does. inline bool monomialHasStrictlyLargerExponent( ConstMonomial hasLarger, ConstMonomial smaller1, ConstMonomial smaller2) const; void monomialParse(std::istream& i, Monomial& result) const; void monomialDisplay(std::ostream& o, ConstMonomial a, bool print_comp=true, bool print_one=true) const; void monomialDisplay(FILE* file, ConstMonomial a, bool printComponent = true, bool printOne = true) const; void printMonomialFrobbyM2Format(std::ostream& out, ConstMonomial m) const; /////////////////////////////////////////// /////////////////////////////////////////// const Monoid& monoid() const {return mMonoid;} const Field& field() const {return mField;} private: Field mField; Monoid mMonoid; }; inline exponent PolyRing::weight(ConstMonomial a) const { return monoid().degree(a); } //////////////////////////////////////////////// // New Monomial Routines /////////////////////// //////////////////////////////////////////////// inline bool PolyRing::monomialEQ(ConstMonomial a, ConstMonomial b) const { return monoid().equal(a, b); } inline bool PolyRing::monomialEqualHintTrue( const ConstMonomial a, const ConstMonomial b ) const { return monoid().equalHintTrue(a, b); } inline bool PolyRing::monomialIsProductOfHintTrue( const ConstMonomial a, const ConstMonomial b, const ConstMonomial ab ) const { return monoid().isProductOfHintTrue(a, b, ab); } MATHICGB_INLINE bool PolyRing::monomialIsTwoProductsOfHintTrue( const ConstMonomial a1, const ConstMonomial a2, const ConstMonomial b, const ConstMonomial a1b, const ConstMonomial a2b ) const { return monoid().isTwoProductsOfHintTrue(a1, a2, b, a1b, a2b); } inline bool PolyRing::monomialIsProductOf( ConstMonomial a, ConstMonomial b, ConstMonomial ab ) const { return monoid().isProductOf(a, b, ab); } inline void PolyRing::monomialMult(ConstMonomial a, ConstMonomial b, Monomial &result) const { monoid().multiply(a, b, result); } inline void PolyRing::setWeightsOnly(Monomial& a1) const { monoid().setOrderData(a1); } inline void PolyRing::setHashOnly(Monomial& a1) const { monoid().setHash(a1); } inline int PolyRing::monomialCompare(ConstMonomial a, ConstMonomial b) const // returns LT, EQ or GT { return monoid().compare(a, b); } inline bool PolyRing::monomialIsDivisibleBy(ConstMonomial a, ConstMonomial b) const { return monoid().divides(b, a); } inline void PolyRing::monomialDivide(ConstMonomial a, ConstMonomial b, Monomial& result) const { return monoid().divide(b, a, result); } inline void PolyRing::monomialColons( ConstMonomial a, ConstMonomial b, monomial aColonB, monomial bColonA ) const { monoid().colons(a, b, aColonB, bColonA); } inline void PolyRing::monomialDivideToNegative(ConstMonomial a, ConstMonomial b, Monomial& result) const { monoid().divideToNegative(b, a, result); } inline bool PolyRing::monomialRelativelyPrime(ConstMonomial a, ConstMonomial b) const { return monoid().relativelyPrime(a, b); } inline void PolyRing::monomialLeastCommonMultiple( ConstMonomial a, ConstMonomial b, Monomial& l) const { monoid().lcm(a, b, l); } inline bool PolyRing::monomialHasStrictlyLargerExponent( ConstMonomial hasLarger, ConstMonomial smaller1, ConstMonomial smaller2) const { return !monoid().dividesLcm(hasLarger, smaller1, smaller2); } //////////////////////////////////////////////// // Old Monomial Routines /////////////////////// //////////////////////////////////////////////// inline bool PolyRing::monomialIsLeastCommonMultiple( ConstMonomial a, ConstMonomial b, ConstMonomial l) const { return monoid().isLcm(a, b, l); } inline void PolyRing::coefficientReciprocalTo(coefficient& result) const { result = field().inverse(field().toElementInRange(result)).value(); } inline void PolyRing::coefficientDivide(coefficient a, coefficient b, coefficient &result) const // result = a/b { result = field().quotient (field().toElementInRange(a), field().toElementInRange(b)).value(); } inline void PolyRing::coefficientFromInt(coefficient &result, int a) const { result = field().toElement(a).value(); } inline void PolyRing::coefficientAddOneTo(coefficient &result) const { result = field().plusOne(field().toElementInRange(result)).value(); } inline void PolyRing::coefficientNegateTo(coefficient& result) const { result = field().negative(field().toElementInRange(result)).value(); } inline coefficient PolyRing::toCoefficient(const int64 value) const { return field().toElement(value).value(); } inline coefficient PolyRing::coefficientNegate(const coefficient coeff) const { return field().negative(field().toElementInRange(coeff)).value(); } inline coefficient PolyRing::coefficientNegateNonZero( const coefficient coeff ) const { return field().negativeNonZero(field().toElementInRange(coeff)).value(); } inline coefficient PolyRing::coefficientSubtract( const coefficient a, const coefficient b ) const { return field().difference (field().toElementInRange(a), field().toElementInRange(b)).value(); } inline void PolyRing::coefficientAddTo (coefficient &result, coefficient a, coefficient b) const // result += a*b { const auto prod = field().product(field().toElementInRange(a), field().toElementInRange(b)); result = field().sum(field().toElementInRange(result), prod).value(); } inline void PolyRing::coefficientAddTo(coefficient &result, coefficient a) const // result += a { result = field().sum (field().toElementInRange(result), field().toElementInRange(a)).value(); } inline void PolyRing::coefficientMultTo (coefficient &result, coefficient a) const // result *= a { result = field().product (field().toElementInRange(result), field().toElementInRange(a)).value(); } inline void PolyRing::coefficientMult (coefficient a, coefficient b, coefficient &result) const { result = field().product (field().toElementInRange(a), field().toElementInRange(b)).value(); } inline bool PolyRing::monomialHasAmpleCapacity(ConstMonomial mono) const { return monoid().hasAmpleCapacity(mono); } /// Returns true if a and b are the same object. inline bool operator==(const PolyRing& a, const PolyRing& b) { return &a == &b; } /// As !(a == b). inline bool operator!=(const PolyRing& a, const PolyRing& b) { return !(a == b); } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/PrimeField.hpp000077500000000000000000000241071311555162500212360ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_PRIME_FIELD_GUARD #define MATHICGB_PRIME_FIELD_GUARD #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// Implements arithmetic in a prime field. T must be an unsigned integer type /// that is used to store the elements of the field. The characteristic of the /// field must be a prime not exceeding std::numeric_limits::max(). template class PrimeField { public: typedef T RawElement; class Element { public: // Re-instate this assert once all code has moved to using PrimeField // properly so that coefficients are no longer signed. //static_assert(!std::numeric_limits::is_signed, ""); static_assert(std::numeric_limits::is_integer, ""); /// This constructor/conversion needs to go away as soon as all code /// has been converted to using PrimeField properly. Kill it with fire! Element(const RawElement& e): mValue(e) {} /// This conversion needs to go away as soon as all code /// has been converted to using PrimeField properly. Kill it with fire! operator RawElement&() {return mValue;} /// This conversion needs to go away as soon as all code /// has been converted to using PrimeField properly. Kill it with fire! operator const RawElement&() const {return mValue;} /// This method needs to go away as soon as all code /// has been converted to using PrimeField properly. Kill it with fire! bool operator==(const RawElement e) const {return value() == e.value();} /// This method needs to go away as soon as all code /// has been converted to using PrimeField properly. Kill it with fire! bool operator!=(const RawElement e) const {return !(*this == e);} Element(const Element& e): mValue(e.value()) {} Element& operator=(const Element& e) { mValue = e.value(); return *this; } bool operator==(const Element e) const {return value() == e.value();} bool operator!=(const Element e) const {return !(*this == e);} T value() const {return mValue;} private: friend class PrimeField; // Uncomment this constructor once the public one is gone. //Element(const T value): mValue(value) {} friend class PrimeFile; T mValue; }; typedef Element& ElementRef; typedef const Element& ConstElementRef; typedef Element* ElementPtr; typedef const Element* ConstElementPtr; typedef std::vector ElementVector; PrimeField(const T primeCharacteristic): mCharac(primeCharacteristic) {} Element zero() const {return Element(0);} Element one() const {return Element(1);} Element minusOne() const {return Element(charac() - 1);} bool isZero(const Element a) const {return a == zero();} bool isOne(const Element a) const {return a == one();} /// Returns true if a is strictly in the upper half of the range of values. /// These can be considered as a negative number with smaller absolute /// value, which can be useful for example when printing the value. bool isNegative(const Element a) const { return a.value() > (charac() + 1) / 2; } T charac() const {return mCharac;} /// Assumes that i is in the range [0;charac()). template Element toElementInRange(Integer&& i) const { typedef typename std::remove_reference::type NoRefInteger; static_assert(std::numeric_limits::is_integer, ""); MATHICGB_ASSERT(0 <= i); typedef typename std::make_unsigned::type Unsigned; //replace the below assert with this uncommented one once we get rid //of signed element types. //MATHICGB_ASSERT(static_cast(i) < charac()); MATHICGB_ASSERT(i < charac()); return Element(i); } template Element toElement(Integer&& i) const { typedef typename std::remove_reference::type NoRefInteger; static_assert(std::numeric_limits::is_integer, ""); // We need to take the modulus of i to put it into the range [0;charac()). // That is more tricky to get right than it might seem. // // The sign of a % b is implementation defined in C++ if either of a or b // are negative. We need the positive remainder so the operands have to be // positive. Another reason for this is that we could not allow b to be // converted to a signed integer since it might not be representable that // way. // // If Integer is signed and i is std::numeric_limits::min() then // it is undefined behavior to evaluate the expression -i since -i is not // representable, leading to a signed overflow. So we have to cast to // unsigned before doing the minus. typedef typename std::make_unsigned::type Unsigned; if (i < 0) { // Negate i to get a positive number, then negate again to cancel out // the first negation. The first cast to unsigned is to avoid // undefined behavior from -i. The second is there because apparently, // at least on GCC, the unary - re-introduces signed and we need to // be unsigned to avoid sign extension. We need zero extension. const auto unsignedNegative = static_cast(-static_cast(i)); return negative(Element(unsignedNegative % charac())); } else return Element(static_cast(i) % charac()); } T toValue(Element e) const {return e.value;} Element sum(const Element a, const Element b) const { const auto s = a.value() + b.value(); // The sum overflowed if and only if a.value() > s. In that case // subtraction of charac() will overflow again in the other direction, // leaving us with the correct result. // @todo: extend precision to rule out overflow without a branch. if (a.value() > s || s >= charac()) { MATHICGB_ASSERT(s - charac() < charac()); return Element(s - charac()); } else return Element(s); } Element plusOne(const Element a) const { const auto s = a.value() + 1; if (s == charac()) return Element(0); else return Element(s); } Element difference(const Element a, const Element b) const { if (a.value() < b.value()) { MATHICGB_ASSERT(a.value() - b.value() + charac() < charac()); return Element(a.value() - b.value() + charac()); } else return Element(a.value() - b.value()); } Element negative(const Element a) const { if (a.value() == 0) return a; else return negativeNonZero(a); } Element negativeNonZero(const Element a) const { MATHICGB_ASSERT(!isZero(a)); return Element(charac() - a.value()); } Element product(const Element a, const Element b) const; /// Returns a times the inverse of b. Element quotient(const Element a, const Element b) const { return product(a, inverse(b)); } /// Returns the multiplicative inverse a^-1 mod charac(). a must not be zero. Element inverse(const Element a) const; private: const T mCharac; }; namespace PrimeFieldInternal { template struct ModularProdType {}; template<> struct ModularProdType {typedef uint16 type;}; template<> struct ModularProdType {typedef uint32 type;}; template<> struct ModularProdType {typedef uint64 type;}; template<> struct ModularProdType {typedef int16 type;}; template<> struct ModularProdType {typedef int32 type;}; template<> struct ModularProdType {typedef int64 type;}; // @todo: Remove this typedef when possible. 64 bits is not enough // to store a 64 bit product. We need it right now because // coefficients are handled as 64 bit in the legacy PolyRing. template<> struct ModularProdType {typedef uint64 type;}; template<> struct ModularProdType {typedef uint64 type;}; template<> struct ModularProdType {typedef uint64 type;}; template<> struct ModularProdType {typedef uint64 type;}; } template auto PrimeField::product( const Element a, const Element b ) const -> Element { typedef typename PrimeFieldInternal::ModularProdType::type BigT; BigT bigProd = static_cast(a.value()) * b.value(); MATHICGB_ASSERT(a.value() == 0 || bigProd / a.value() == b.value()); return Element(static_cast(bigProd % charac())); } template auto PrimeField::inverse(const Element elementA) const -> Element { // We do two turns of the extended Euclidian algorithm per // loop. Usually the sign of x changes each time through the loop, // but we avoid that by representing every other x as its negative, // which is the value minusLastX. This way no negative values ever // appear and we do not need any extra bits. auto a = elementA.value(); MATHICGB_ASSERT(0 < a); MATHICGB_ASSERT(a < charac()); #ifdef MATHICGB_DEBUG const auto origA = a; #endif auto b = charac(); auto minusLastX = static_cast(0); auto x = static_cast(1); while (true) { MATHICGB_ASSERT(x <= charac()); MATHICGB_ASSERT(minusLastX <= charac()); // first turn if (a == 1) break; const auto firstQuotient = b / a; b -= firstQuotient * a; minusLastX += firstQuotient * x; // second turn if (b == 1) { MATHICGB_ASSERT(!isZero(minusLastX)); MATHICGB_ASSERT(minusLastX < charac()); x = charac() - minusLastX; break; } const auto secondQuotient = a / b; a -= secondQuotient * b; x += secondQuotient * minusLastX; } MATHICGB_ASSERT(x >= 1); MATHICGB_ASSERT(x < charac()); const Element inverseElement(x); MATHICGB_ASSERT(isOne(product(elementA, inverseElement))); return inverseElement; } /// Returns true if a and b are the same object. template bool operator==(const PrimeField& a, const PrimeField& b) { return &a == &b; } /// As !(a == b). template bool operator!=(const PrimeField& a, const PrimeField& b) { return !(a == b); } template std::ostream& operator<<( std::ostream& out, typename PrimeField::Element e ) { out << e.value(); return out; } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/QuadMatrix.cpp000077500000000000000000000264031311555162500212710ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "QuadMatrix.hpp" #include "MathicIO.hpp" #include "mtbb.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN bool QuadMatrix::debugAssertValid() const { #ifndef MATHICGB_DEBUG return true; #else MATHICGB_ASSERT(topLeft.debugAssertValid()); MATHICGB_ASSERT(bottomLeft.debugAssertValid()); MATHICGB_ASSERT(topRight.debugAssertValid()); MATHICGB_ASSERT(bottomRight.debugAssertValid()); if (!leftColumnMonomials.empty() || !rightColumnMonomials.empty()) { MATHICGB_ASSERT(topLeft.computeColCount() <= leftColumnMonomials.size()); MATHICGB_ASSERT(bottomLeft.computeColCount() <= leftColumnMonomials.size()); MATHICGB_ASSERT(topRight.computeColCount() <= rightColumnMonomials.size()); MATHICGB_ASSERT(bottomRight.computeColCount() <= rightColumnMonomials.size()); } MATHICGB_ASSERT(topLeft.rowCount() == topRight.rowCount()); MATHICGB_ASSERT(bottomRight.rowCount() == bottomLeft.rowCount()); return true; #endif } void QuadMatrix::print(std::ostream& out) const { MATHICGB_ASSERT(debugAssertValid()); typedef SparseMatrix::ColIndex ColIndex; mathic::ColumnPrinter printer; printer.addColumn(true, "", ""); printer.addColumn(true, " | ", ""); // column monomials out << "Left columns:"; for (const auto& mono : leftColumnMonomials) { out << ' '; MathicIO<>().writeMonomial(monoid(), false, *mono, out); } out << "\nRight columns:"; for (const auto& mono : rightColumnMonomials) { out << ' '; MathicIO<>().writeMonomial(monoid(), false, *mono, out); } out << '\n'; // left side topLeft.print(printer[0]); printer[0] << '\n'; bottomLeft.print(printer[0]); // right side topRight.print(printer[1]); printer[1] << '\n'; bottomRight.print(printer[1]); out << printer; } size_t QuadMatrix::rowCount() const { return topLeft.rowCount() + bottomLeft.rowCount(); } SparseMatrix::ColIndex QuadMatrix::computeLeftColCount() const { if (!leftColumnMonomials.empty()) { MATHICGB_ASSERT( leftColumnMonomials.size() <= std::numeric_limits::max() ); return static_cast(leftColumnMonomials.size()); } return std::max(topLeft.computeColCount(), bottomLeft.computeColCount()); } SparseMatrix::ColIndex QuadMatrix::computeRightColCount() const { if (!rightColumnMonomials.empty()) { MATHICGB_ASSERT( rightColumnMonomials.size() <= std::numeric_limits::max() ); return static_cast(rightColumnMonomials.size()); } return std::max(topRight.computeColCount(), bottomRight.computeColCount()); } size_t QuadMatrix::entryCount() const { return topLeft.entryCount() + topRight.entryCount() + bottomLeft.entryCount() + bottomRight.entryCount(); } std::string QuadMatrix::toString() const { std::ostringstream out; print(out); return out.str(); } size_t QuadMatrix::memoryUse() const { return topLeft.memoryUse() + topRight.memoryUse() + bottomLeft.memoryUse() + bottomRight.memoryUse(); } size_t QuadMatrix::memoryUseTrimmed() const { return topLeft.memoryUseTrimmed() + topRight.memoryUseTrimmed() + bottomLeft.memoryUseTrimmed() + bottomRight.memoryUseTrimmed(); } void QuadMatrix::printStatistics(std::ostream& out) const { typedef mathic::ColumnPrinter ColPr; ColPr pr; pr.addColumn(false, " ", ""); pr.addColumn(false, "", ""); pr.addColumn(false, "", ""); pr.addColumn(false, "", ""); pr.addColumn(true, "", ""); const auto totalMemory = memoryUse(); auto printDataCol = [&]( std::ostream& out, const SparseMatrix& top, const SparseMatrix& bottom, const SparseMatrix::ColIndex colCount ) { auto printDataCell = [&](const SparseMatrix& matrix) { const auto entryCount = matrix.entryCount(); const uint64 area = static_cast(matrix.rowCount()) * static_cast(colCount); const auto memory = matrix.memoryUse(); out << ColPr::withSIPrefix(entryCount) << " -" << ColPr::percentIntegerFixed(entryCount, area) << " \n" << ColPr::bytesInUnit(memory) << " -" << ColPr::percentIntegerFixed(matrix.memoryUseTrimmed(), memory) << " \n" << ColPr::percentInteger(memory, totalMemory) << " \n"; }; out << ColPr::commafy(colCount) << " \n"; const char* const line = "------------------\n"; out << line; printDataCell(top); out << line; printDataCell(bottom); out << line; }; pr[0] << "\n/\n" << ColPr::commafy(topLeft.rowCount()) << " |\nrows |\n|\n|\n" << ColPr::commafy(bottomLeft.rowCount()) << " |\nrows |\n|\n\\\n"; printDataCol(pr[1], topLeft, bottomLeft, computeLeftColCount()); pr[2] << " \n|\n|\n|\n|\n|\n|\n|\n|\n|\n"; printDataCol(pr[3], topRight, bottomRight, computeRightColCount()); const char* const legend = "| non-zero (density)\n| memory (used)\n| of total memory\n"; pr[4] << " columns\n\\\n" << legend << "|\n" << legend << "/\n"; out << '\n' << pr << " Total memory: " << ColPr::bytesInUnit(memoryUse()) << " (" << ColPr::percentInteger(memoryUseTrimmed(), totalMemory) << " used)\n\n"; } QuadMatrix QuadMatrix::toCanonical() const { class RowComparer { public: RowComparer(const SparseMatrix& matrix): mMatrix(matrix) {} bool operator()(SparseMatrix::RowIndex a, SparseMatrix::RowIndex b) const { auto itA = mMatrix.rowBegin(a); const auto endA = mMatrix.rowEnd(a); auto itB = mMatrix.rowBegin(b); const auto endB = mMatrix.rowEnd(b); for (; itA != endA; ++itA, ++itB) { if (itB == endB) return true; if (itA.index() > itB.index()) return true; if (itA.index() < itB.index()) return false; if (itA.scalar() > itB.scalar()) return false; if (itA.scalar() < itB.scalar()) return true; } return false; } private: const SparseMatrix& mMatrix; }; const auto leftColCount = leftColumnMonomials.size(); const auto rightColCount = rightColumnMonomials.size(); // todo: eliminate left/right code duplication here QuadMatrix matrix(ring()); { // left side std::vector rows; for (SparseMatrix::RowIndex row = 0; row < topLeft.rowCount(); ++row) rows.push_back(row); { RowComparer comparer(topLeft); std::sort(rows.begin(), rows.end(), comparer); } matrix.topLeft.clear(); matrix.topRight.clear(); for (SparseMatrix::RowIndex i = 0; i < rows.size(); ++i) { matrix.topLeft.appendRow(topLeft, rows[i]); matrix.topRight.appendRow(topRight, rows[i]); } } { // right side std::vector rows; for (SparseMatrix::RowIndex row = 0; row < bottomLeft.rowCount(); ++row) rows.push_back(row); { RowComparer comparer(bottomLeft); std::sort(rows.begin(), rows.end(), comparer); } matrix.bottomLeft.clear(); matrix.bottomRight.clear(); for (SparseMatrix::RowIndex i = 0; i < rows.size(); ++i) { matrix.bottomLeft.appendRow(bottomLeft, rows[i]); matrix.bottomRight.appendRow(bottomRight, rows[i]); } } matrix.leftColumnMonomials = leftColumnMonomials; matrix.rightColumnMonomials = rightColumnMonomials; return std::move(matrix); } std::ostream& operator<<(std::ostream& out, const QuadMatrix& qm) { qm.print(out); return out; } namespace { template class ColumnComparer { public: ColumnComparer(const Monoid& monoid): mMonoid(monoid) {} template bool operator()(const Pair& a, const Pair b) const { return mMonoid.lessThan(*b.first, *a.first); } private: const Monoid& mMonoid; }; std::vector sortColumnMonomialsAndMakePermutation( QuadMatrix::Monomials& monomials, const QuadMatrix::Monoid& monoid ) { typedef SparseMatrix::ColIndex ColIndex; MATHICGB_ASSERT(monomials.size() <= std::numeric_limits::max()); const ColIndex colCount = static_cast(monomials.size()); // Monomial needs to be non-const as we are going to put these // monomials back into the vector of monomials which is not const. std::vector> columns; columns.reserve(colCount); for (ColIndex col = 0; col < colCount; ++col) columns.push_back(std::make_pair(monomials[col], col)); std::sort( columns.begin(), columns.end(), ColumnComparer(monoid) ); // Apply sorting permutation to monomials. This is why it is necessary to // copy the values in monomial out of there: in-place application of a // permutation is messy. MATHICGB_ASSERT(columns.size() == colCount); MATHICGB_ASSERT(monomials.size() == colCount); for (size_t col = 0; col < colCount; ++col) { MATHICGB_ASSERT( col == 0 || monoid.lessThan(*columns[col].first, *columns[col - 1].first) ); monomials[col] = columns[col].first; } // Construct permutation of indices to match permutation of monomials std::vector permutation(colCount); for (ColIndex col = 0; col < colCount; ++col) { // The monomial for column columns[col].second is now the // monomial for col, so we need the inverse map for indices. permutation[columns[col].second] = col; } return std::move(permutation); } } void QuadMatrix::sortColumnsLeftRightParallel() { typedef SparseMatrix::ColIndex ColIndex; std::vector leftPermutation; std::vector rightPermutation; mgb::mtbb::parallel_for(0, 2, 1, [&](int i) { if (i == 0) leftPermutation = sortColumnMonomialsAndMakePermutation(leftColumnMonomials, monoid()); else rightPermutation = sortColumnMonomialsAndMakePermutation(rightColumnMonomials, monoid()); }); mgb::mtbb::parallel_for(0, 4, 1, [&](int i) { if (i == 0) topRight.applyColumnMap(rightPermutation); else if (i == 1) bottomRight.applyColumnMap(rightPermutation); else if (i == 2) topLeft.applyColumnMap(leftPermutation); else { MATHICGB_ASSERT(i == 3); bottomLeft.applyColumnMap(leftPermutation); } }); } void QuadMatrix::write( const SparseMatrix::Scalar modulus, FILE* file ) const { MATHICGB_ASSERT(file != 0); topLeft.write(modulus, file); topRight.write(modulus, file); bottomLeft.write(modulus, file); bottomRight.write(modulus, file); } SparseMatrix::Scalar QuadMatrix::read(FILE* file) { MATHICGB_ASSERT(file != 0); leftColumnMonomials.clear(); rightColumnMonomials.clear(); const auto topLeftModulus = topLeft.read(file); const auto topRightModulus = topRight.read(file); const auto bottomLeftModulus = bottomLeft.read(file); const auto bottomRightModulus = bottomRight.read(file); // todo: this should throw some kind of invalid format exception instead of // these asserts. MATHICGB_ASSERT(topLeftModulus == topRightModulus); MATHICGB_ASSERT(bottomLeftModulus == topRightModulus); MATHICGB_ASSERT(bottomRightModulus == topRightModulus); MATHICGB_ASSERT(debugAssertValid()); return topLeftModulus; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/QuadMatrix.hpp000077500000000000000000000067341311555162500213030ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_QUAD_MATRIX_GUARD #define MATHICGB_QUAD_MATRIX_GUARD #include "PolyRing.hpp" #include "SparseMatrix.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN /// Represents a matrix composed of 4 sub-matrices that fit together /// into one matrix divided into top left, top right, bottom left and /// bottom right. This is a convenient representation of the matrices /// encountered in the F4 polynomial reduction algorithm. class QuadMatrix { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; QuadMatrix(): mRing(nullptr) {} QuadMatrix(const PolyRing& ring): mRing(&ring) {} QuadMatrix(QuadMatrix&& matrix): topLeft(std::move(matrix.topLeft)), topRight(std::move(matrix.topRight)), bottomLeft(std::move(matrix.bottomLeft)), bottomRight(std::move(matrix.bottomRight)), leftColumnMonomials(std::move(matrix.leftColumnMonomials)), rightColumnMonomials(std::move(matrix.rightColumnMonomials)), mRing(&matrix.ring()) {} QuadMatrix& operator=(QuadMatrix&& matrix) { MATHICGB_ASSERT(mRing == matrix.mRing); this->~QuadMatrix(); new (this) QuadMatrix(std::move(matrix)); return *this; } void clear() { *this = QuadMatrix(ring()); } typedef std::vector Monomials; SparseMatrix topLeft; SparseMatrix topRight; SparseMatrix bottomLeft; SparseMatrix bottomRight; Monomials leftColumnMonomials; Monomials rightColumnMonomials; /// Prints whole matrix to out in human-readable format. Useful for /// debugging. void print(std::ostream& out) const; void printStatistics(std::ostream& out) const; size_t memoryUse() const; size_t memoryUseTrimmed() const; /// Shows whole matrix in a string. Useful for debugging. std::string toString() const; /// Return the combined number of non-zero entries. size_t entryCount() const; /// Return the combined number of left and right columns. size_t rowCount() const; /// Return the number of left columns. SparseMatrix::ColIndex computeLeftColCount() const; /// Return the number of right columns. SparseMatrix::ColIndex computeRightColCount() const; void write(SparseMatrix::Scalar modulus, FILE* file) const; /// Read a matrix from file into *this. Return the modulus from file. /// This method clears the column monomials and the ring pointer. SparseMatrix::Scalar read(FILE* file); /// Sort the left columns to be in decreasing order according to the monomial /// order from the ring. The operation is done in parallel. void sortColumnsLeftRightParallel(); /// Makes a copy of this matrix whose rows are sorted in some canonical way. /// TODO: Actually only coarsely sorts the top rows right now. QuadMatrix toCanonical() const; /// Asserts internal invariants if asserts are turned on. bool debugAssertValid() const; const PolyRing& ring() const {return *mRing;} const Monoid& monoid() const {return ring().monoid();} private: QuadMatrix(const QuadMatrix&); // not available void operator=(const QuadMatrix&); // not available const PolyRing* const mRing; }; std::ostream& operator<<(std::ostream& out, const QuadMatrix& qm); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/QuadMatrixBuilder.cpp000077500000000000000000000074231311555162500226010ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "QuadMatrixBuilder.hpp" #include "QuadMatrix.hpp" #include "ScopeExit.hpp" #include #include MATHICGB_NAMESPACE_BEGIN QuadMatrixBuilder::QuadMatrixBuilder( const PolyRing& ring, Map& map, Monomials& monomialsLeft, Monomials& monomialsRight, const size_t memoryQuantum ): mMonomialToCol(map), mTopLeft(memoryQuantum), mTopRight(memoryQuantum), mBottomLeft(memoryQuantum), mBottomRight(memoryQuantum), mMonomialsLeft(monomialsLeft), mMonomialsRight(monomialsRight) {} void QuadMatrixBuilder::takeRowsFrom(QuadMatrix&& matrix) { MATHICGB_ASSERT(&ring() == &matrix.ring()); MATHICGB_ASSERT(matrix.debugAssertValid()); mTopLeft.takeRowsFrom(std::move(matrix.topLeft)); mTopRight.takeRowsFrom(std::move(matrix.topRight)); mBottomLeft.takeRowsFrom(std::move(matrix.bottomLeft)); mBottomRight.takeRowsFrom(std::move(matrix.bottomRight)); } namespace { /// Creates a column and updates the associated data structures that /// are passed in. Copies mono - ownership is not taken over. The /// purpose of this function is to avoid code duplication. It is a /// template in order to avoid referring to private types of /// QuadMatrixBuilder. template std::pair createCol( typename Monoid::ConstMonoRef mono, SparseMatrix& top, SparseMatrix& bottom, ToMono& toMonomial, ToCol& toCol, const Monoid& monoid, const bool left ) { MATHICGB_ASSERT(typename ToCol::Reader(toCol).find(mono).first == 0); const auto colCount = static_cast(toMonomial.size()); if (colCount == std::numeric_limits::max()) throw std::overflow_error("Too many columns in QuadMatrixBuilder"); // allocate memory in toMonomial now to ensure no bad_alloc later toMonomial.emplace_back(nullptr); MATHICGB_SCOPE_EXIT(toMonomialGuard) {toMonomial.pop_back();}; auto copied = monoid.alloc(); monoid.copy(mono, copied); auto inserted = toCol.insert( std::make_pair( copied.ptr(), QuadMatrixBuilder::LeftRightColIndex(colCount, left) ) ); MATHICGB_ASSERT(inserted.second); MATHICGB_ASSERT(inserted.first.first != 0); auto p(inserted.first); toMonomial.back() = copied; MATHICGB_ASSERT(monoid.equalHintTrue(*copied, *p.second)); MATHICGB_ASSERT(*p.first == QuadMatrixBuilder::LeftRightColIndex(colCount, left)); auto ptr = const_cast(Monoid::toOld(*p.second)); toMonomialGuard.dismiss(); copied.release(); return std::make_pair(*p.first, ptr); } } std::pair QuadMatrixBuilder::createColumnLeft( ConstMonoRef monomialToBeCopied ) { return createCol( monomialToBeCopied, mTopLeft, mBottomLeft, mMonomialsLeft, mMonomialToCol, monoid(), true ); } std::pair QuadMatrixBuilder::createColumnRight( ConstMonoRef monomialToBeCopied ) { return createCol( monomialToBeCopied, mTopRight, mBottomRight, mMonomialsRight, mMonomialToCol, monoid(), false ); } QuadMatrix QuadMatrixBuilder::buildMatrixAndClear() { QuadMatrix out(ring()); mTopLeft.swap(out.topLeft); mTopRight.swap(out.topRight); mBottomLeft.swap(out.bottomLeft); mBottomRight.swap(out.bottomRight); mTopLeft.clear(); mTopRight.clear(); mBottomLeft.clear(); mBottomRight.clear(); MATHICGB_ASSERT(out.debugAssertValid()); return std::move(out); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/QuadMatrixBuilder.hpp000077500000000000000000000150071311555162500226030ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_QUAD_MATRIX_BUILDER_GUARD #define MATHICGB_QUAD_MATRIX_BUILDER_GUARD #include "MonomialMap.hpp" #include "SparseMatrix.hpp" #include "PolyRing.hpp" #include #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN class QuadMatrix; /// Builder for QuadMatrix. This is not quite the builder pattern in /// that the interface is not virtual and the implementation cannot be /// swapped out - it only follows the builder pattern in that it is a /// class that allows step-wise construction of a final product. class QuadMatrixBuilder { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef SparseMatrix::RowIndex RowIndex; typedef SparseMatrix::ColIndex ColIndex; typedef SparseMatrix::Scalar Scalar; /// The index of a column that can be either on the left or the /// right side. The largest representable ColIndex is an invalid /// index. This is the default value. The only allowed method to /// call for an invalid index is valid(). class LeftRightColIndex { public: LeftRightColIndex(): mRawIndex(std::numeric_limits::max()), mLeft(false) {} LeftRightColIndex(ColIndex index, bool left): mRawIndex(index), mLeft(left) {} ColIndex leftIndex() const { MATHICGB_ASSERT(left()); return index(); } ColIndex rightIndex() const { MATHICGB_ASSERT(right()); return index(); } /// Use leftIndex() or rightIndex() instead if you know what side /// you are expecting, as those do an assert on your expectation. ColIndex index() const { MATHICGB_ASSERT(valid()); return mRawIndex; } bool left() const { MATHICGB_ASSERT(valid()); return mLeft; } bool right() const { MATHICGB_ASSERT(valid()); return !left(); } bool valid() const { return mRawIndex != std::numeric_limits::max(); } bool operator==(const LeftRightColIndex& index) const { return mRawIndex == index.mRawIndex && mLeft == index.mLeft; } bool operator!=(const LeftRightColIndex& index) const { return !(*this == index); } private: ColIndex mRawIndex; bool mLeft; }; typedef MonomialMap Map; typedef std::vector Monomials; QuadMatrixBuilder( const PolyRing& ring, Map& map, Monomials& monomialsLeft, Monomials& monomialsRight, size_t memoryQuantum = 0 ); /// Inserts the rows from builder. To avoid an assert either the matrix must /// have no column monomials specified or the monomials that are specified /// must match exactly to the column monomials for this object --- including /// the ordering of the monomials. void takeRowsFrom(QuadMatrix&& matrix); size_t memoryQuantum() const { return mTopLeft.memoryQuantum(); } // **** Appending entries to top matrices. // Same interface as SparseMatrix except with two matrices and here // you have to create columns before you can use them. void appendEntryTopLeft(ColIndex col, Scalar scalar) { mTopLeft.appendEntry(col, scalar); } void appendEntryTopRight(ColIndex col, Scalar scalar) { mTopRight.appendEntry(col, scalar); } void appendEntryTop(LeftRightColIndex col, Scalar scalar) { MATHICGB_ASSERT(col.valid()); if (col.left()) appendEntryTopLeft(col.leftIndex(), scalar); else appendEntryTopRight(col.rightIndex(), scalar); } void rowDoneTopLeftAndRight() { mTopLeft.rowDone(); mTopRight.rowDone(); } // **** Appending entries to bottom matrices // Same interface as SparseMatrix except with two matrices and here // you have to create columns before you can use them. void appendEntryBottomLeft(ColIndex col, Scalar scalar) { mBottomLeft.appendEntry(col, scalar); } void appendEntryBottomRight(ColIndex col, Scalar scalar) { mBottomRight.appendEntry(col, scalar); } void appendEntryBottom(LeftRightColIndex col, Scalar scalar) { MATHICGB_ASSERT(col.valid()); if (col.left()) appendEntryBottomLeft(col.leftIndex(), scalar); else appendEntryBottomRight(col.rightIndex(), scalar); } void rowDoneBottomLeftAndRight() { mBottomLeft.rowDone(); mBottomRight.rowDone(); } // *** Creating and reordering columns // You have to create columns before you can append entries in those columns. // All passed in monomials are copied so that ownership of the memory is // not taken over. The creation methods return a LeftRightColIndex instead // of just a ColIndex to allow more of a chance for asserts to catch errors // and to avoid the need for the client to immediately construct a // LeftRightColIndex based on the return value. /// Creates a new column associated to the monomial /// monomialToBeCopied to the left matrices. There must not already /// exist a column for this monomial on the left or on the right. std::pair createColumnLeft(ConstMonoRef monomialToBeCopied); /// Creates a new column associated to the monomial monomialToBeCopied /// to the right matrices. There must not already exist a column for /// this monomial on the left or on the right. std::pair createColumnRight(ConstMonoRef monomialToBeCopied); // *** Querying columns const SparseMatrix& topLeft() const {return mTopLeft;} const SparseMatrix& topRight() const {return mTopRight;} const SparseMatrix& bottomLeft() const {return mBottomLeft;} const SparseMatrix& bottomRight() const {return mBottomRight;} const PolyRing& ring() const {return mMonomialToCol.ring();} const Monoid& monoid() const {return ring().monoid();} /// Returns the built matrix and sets the builder to a state /// with no columns and no rows. QuadMatrix buildMatrixAndClear(); private: Monomials& mMonomialsLeft; /// stores one monomial per left column Monomials& mMonomialsRight; /// stores one monomial per right column /// Used for fast determination of which column has a given monomial. Map& mMonomialToCol; SparseMatrix mTopLeft; SparseMatrix mTopRight; SparseMatrix mBottomLeft; SparseMatrix mBottomRight; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/Range.hpp000077500000000000000000000407021311555162500202510ustar00rootroot00000000000000// MathicGB copyright 2013 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_RANGE_GUARD #define MATHICGB_RANGE_GUARD #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN // Read on, this file contains several free-standing functions that make use // of the range concept and Range class. /// An object that combines two iterators into a range suitable for use with /// C++11's range for. It is most conveniently used with the function range. /// For example: /// /// std::vector v; /// for (int x : range(v.begin(), v.end()) {} /// /// std::vector already has begin and end members, so range() is not necessary /// here. range() is useful when a class does not have begin or end members, or /// if it offers several different ranges that can be iterated through - /// then the default range can only offer one of those ranges. template class Range { public: typedef Iter Iterator; Range(Iterator begin, Iterator end): mBegin(begin), mEnd(end) {} Range(std::pair pair): mBegin(pair.first), mEnd(pair.second) {} Iterator begin() const {return mBegin;} Iterator end() const {return mEnd;} private: Iterator mBegin; Iterator mEnd; }; /// Convenience function for constructing a Range object. This function /// removes the need to explicitly specify the types involved. template Range range(Iterator begin, Iterator end) { return Range(begin, end); } /// As range(std::begin(r), std::end(r)). template auto range(RangeParam&& r) -> decltype(range(std::begin(r), std::end(r))) { return range(std::begin(r), std::end(r)); } // *** Zipping ranges together /// Zip ties two iterators together into a single iterator. The point /// is to enable the zip() function defined further down in this header. /// /// Note that equality is defined ONLY by equality of the first iterator! template class Zip { public: typedef decltype(*std::declval()) ValueType1; typedef decltype(*std::declval()) ValueType2; /// It would be possible to do something fancy to infer the strongest /// iterator category that both sub-iterators can support. Since this /// is intended mainly to be used for things like range-for, I did not /// implement that since I do not need it. typedef std::forward_iterator_tag iterator_category; typedef std::pair value_type; typedef ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; Zip() {} Zip(Iterator1 it1, Iterator2 it2): mIt1(it1), mIt2(it2) {} Zip& operator++() { ++mIt1; ++mIt2; return *this; } value_type operator*() const { // We cannot use std::make_pair here. If .first or .second is a // reference, then std::make_pair will remove the reference and then the // conversion to value_type will add the reference back in - but now the // reference is not what was originally referenced, instead it is a // reference to the temporary object returned by std::make_pair, which // then promptly goes out of scope, leading to undefined behavior. return value_type(*mIt1, *mIt2); } /// Compares only the first iterator! bool operator!=(const Zip& it) const {return mIt1 != it.mIt1;} /// Compares only the first iterator! bool operator==(const Zip& it) const {return mIt1 == it.mIt1;} private: Iterator1 mIt1; Iterator2 mIt2; }; /// Creates a Zip iterator out of it1 and it2. This is a convenience function /// that removes the need to specify the iterator types explicitly. /// /// There would rarely (never?) be a need to call this function directly. /// Prefer to call zip() directly. template auto makeZip( const Iterator1& it1, const Iterator2& it2 ) -> Zip { return Zip(it1, it2); } /// As zip(range(begin1, end1), range(begin2, end2)). template auto zip( const Iterator1& begin1, const Iterator1& end1, const Iterator2& begin2, const Iterator2& end2 ) -> decltype(range(makeZip(begin1, begin2), makeZip(end1, end2))) { return range(makeZip(begin1, begin2), makeZip(end1, end2)); } /// Zips two ranges into a single range of pairs. /// /// Example: /// std::vector a = {"hello", "world"}; /// std::vector b = {4, 2, 1, 0}; /// for (const auto& p : zip(a, b)) /// std::cout << p.first << p.second << ' '; /// /// The output will be "hello4 world2 ". If the ranges have different lengths /// then the length of the range will be the length of the first range. If the /// first range is longer than the second one, this means you will likely /// run into undefined behavior. We can't even do an assert for that because /// it's perfectly reasonable to use giant implicitly represented ranges for /// the second parameter and if that's a forward iterator, doing std::distance /// on it might never terminate or take a very long time. template auto zip(Range1&& range1, Range2&& range2) -> decltype( zip( std::begin(range1), std::end(range1), std::begin(range2), std::end(range2) ) ) { return zip( std::begin(range1), std::end(range1), std::begin(range2), std::end(range2) ); } // *** Implicitly represented ranges of integers /// An Iterator that wraps an integer. template class IntIterator { public: /// It could perfectly well be a random access iterator, I just do not /// need that functionality right now, so I'm not implementing it. typedef std::forward_iterator_tag iterator_category; typedef Integer value_type; typedef ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; IntIterator(Integer integer): mInteger(integer) {} value_type operator*() const {return mInteger;} IntIterator& operator++() { ++mInteger; return *this; } bool operator==(const IntIterator& it) const {return **this == *it;} bool operator!=(const IntIterator& it) const {return **this != *it;} private: Integer mInteger; }; /// Constructs a half-open interval of integers [begin, end) that is /// compatible with range-for. /// /// Example: /// for (auto x : intRange(5, 10) /// std::cout << ' ' << x; /// The output will be " 5 6 7 8 9". See indexRange() for further examples /// of how this sort of thing can be useful. template Range> intRange(Integer begin, Integer end) { return Range>(begin, end); } /// As intRange(Integer(0), end). template auto intRange(Integer end) -> decltype(intRange(0, 0)) { return intRange(Integer(0), end); } /// As intRange(0, max) where max is the maximum representable /// integer of type Integer as indicated by std::numeric_limits. inline auto intRange() -> decltype(intRange(0, 0)) { return intRange(0, std::numeric_limits::max()); } /// Adds indices to the elements of the range, specifying the offset of each /// element in the range. Equivalent to zip(range(begin, end), intRange()). /// /// Example: /// const char*[] strs = {"hello", "world", "!"}; /// for (const auto& p : indexRange(strs)) /// std::cout << ' ' << p.first << p.second; /// /// The output will be " hello0 world1 !2". template auto indexRange( const Iterator& begin, const Iterator& end ) -> decltype(zip(range(begin, end), intRange())) { return zip(range(begin, end), intRange()); } /// As indexRange(std::begin(r), std::end(r)). template auto indexRange( Range&& r ) -> decltype(indexRange(std::begin(r), std::end(r))) { return indexRange(std::begin(r), std::end(r)); } // *** Conversion from range to container /// As rangeToVector(range(begin, end)). template auto rangeToVector( Iterator begin, Iterator end ) -> decltype( std::vector::type>(begin, end) ) { return std::vector::type>(begin, end); } /// Converts a range into a vector. This is a convenience function. /// When using this function, it is not necessary to name the type of the /// vector. It is also not necessary to give a name to the range object. /// /// Example: /// const char*[] strs = {"hello", "world", "!"}; /// auto v = rangeToVector(indexRange(strs)); /// /// Without rangeToVector, the last line would have to be replaced by /// /// auto r = indexRange(strs); /// std::vector> v(r.begin(), r.end()); /// /// The return type is std::vector where T is whatever type is contained /// in the range, after stripping references and other qualifiers. So if /// the iterators in the range return const T&, the return type will still /// be std::vector. More precisely, if the returned type is S, the returned /// type will be std::vector::type>. template auto rangeToVector( RangeParam&& range ) -> decltype(rangeToVector(std::begin(range), std::end(range))) { return rangeToVector(std::begin(range), std::end(range)); } // *** Range of adjacent pairs /// Wraps an iterator of pairs to be an iterator of opposite pairs, so that /// if *it == (a, b) then *OppositePairIterator(it) == (b, a). template class OppositePairIterator { public: typedef decltype((*std::declval()).first) InnerValueType1; typedef decltype((*std::declval()).second) InnerValueType2; typedef typename Iterator::iterator_category iterator_category; typedef std::pair value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; OppositePairIterator() {} OppositePairIterator(const Iterator& it): mIt(it) {} OppositePairIterator& operator++() { ++mIt; return *this; } value_type operator*() const { return value_type((*mIt).second, (*mIt).first); } bool operator!=(const OppositePairIterator& it) const {return mIt != it.mIt;} bool operator==(const OppositePairIterator& it) const {return mIt == it.mIt;} private: Iterator mIt; }; /// As oppositePairRange(range(begin, end)). template Range> oppositePairRange( const Iterator& begin, const Iterator& end ) { return range>(begin, end); } /// Swaps the elements of the pairs in a range of pairs. /// /// Example: /// auto print = [](std::pair p) { /// std::cout << '(' << p.first << ',' << p.second << ')'; /// auto r = zip(intRange(1, 3), intRange(101, 103)); /// for (auto p : r) /// print(p); /// std::cout << '\n'; /// for (auto p : oppositePairRange(r)) /// print(p); /// /// The output will be /// /// (1,101)(2,102)(3,103) /// (101,1)(102,2)(103,3) template auto oppositePairRange( RangeParam&& r ) -> decltype(oppositePairRange(std::begin(r), std::end(r))) { return oppositePairRange(std::begin(r), std::end(r)); } /// As adjPairRange(range(begin, end)). template auto adjPairRange( const Iterator& begin, const Iterator& end ) -> decltype(oppositePairRange(zip(end, end, end, end))) { if (begin == end) return oppositePairRange(zip(end, end, end, end)); // This is a bit tricky. What we really want is // zip(begin, end - 1, begin + 1, end) // The -1 is bad because we want this to work for forward iterators // that do not have operator--(). We cannot just leave out the -1 because // zip defines the length of the range according to the first component // range. However, if we swap the ranges around to // zip(begin + 1, end, begin, end - 1) // then we can replace this by // zip(begin + 1, end, begin, end) // because zip does not actually care about the length of the second range. // The problem now is that the pairs of elements will be the wrong way // around, but oppositePairRange solves that nicely. auto pastBegin = begin; ++pastBegin; return oppositePairRange(zip(pastBegin, end, begin, end)); } template auto adjPairRange( RangeParam&& r ) -> decltype(adjPairRange(std::begin(r), std::end(r))) { return adjPairRange(std::begin(r), std::end(r)); } // *** Flatten range of ranges into a single range namespace FlattenNamespace { template struct InnerIteratorType { typedef typename std::decay::type type; }; } /// Flatten is an iterator that iterates through each range in a range /// of ranges. The point is to enable the flatten() function defined /// further down in this header. This iterator is invalidated whenever /// the outer range or any of the inner ranges invalidate any iterator /// or change their number of elements. template class Flatten { public: // Yes, it would inded make more sense to inline what InnerIteratorType<> // does here. That worked fine on gcc 4.7.3. It did not compile on // MSVC 2012. I spent a lot of time trying to track down the problem // and as far as I can tell, it is a compiler bug. The work-around // with InnerIteratorType works and I'm going to leave it at that. typedef typename FlattenNamespace::InnerIteratorType::type InnerIterator; typedef typename std::iterator_traits::difference_type difference_type; typedef typename std::iterator_traits::value_type value_type; typedef typename std::iterator_traits::pointer pointer; typedef typename std::iterator_traits::reference reference; // It would be possible to do something fancy here to identify the exact // most general iterator category. I have not done that since I have not // needed it so far. typedef std::forward_iterator_tag iterator_category; Flatten() {} Flatten(const OuterIterator outerBegin, const OuterIterator outerEnd): mOuter(outerBegin), mOuterEnd(outerEnd) { adjustOuter(); MATHICGB_ASSERT(debugAssertValid()); } Flatten& operator++() { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(!atEnd()); MATHICGB_ASSERT(mInner != std::end(*mOuter)); ++mInner; if (mInner == std::end(*mOuter)) { ++mOuter; adjustOuter(); } MATHICGB_ASSERT(debugAssertValid()); return *this; } decltype(*std::declval()) operator*() const { MATHICGB_ASSERT(!atEnd()); return *mInner; } bool equal(const Flatten& f) const { MATHICGB_ASSERT(debugAssertValid()); MATHICGB_ASSERT(f.debugAssertValid()); if (atEnd()) return f.atEnd(); else if (f.atEnd()) return false; else return mInner == f.mInner; } bool debugAssertValid() const { MATHICGB_ASSERT(atEnd() || mInner != std::end(*mOuter)); return true; } private: bool atEnd() const {return mOuter == mOuterEnd;} void adjustOuter() { for (; !atEnd(); ++mOuter) { if (std::begin(*mOuter) != std::end(*mOuter)) { mInner = std::begin(*mOuter); return; } } } InnerIterator mInner; OuterIterator mOuter; OuterIterator mOuterEnd; }; template bool operator==( const Flatten& a, const Flatten& b ) { return a.equal(b); } template bool operator!=( const Flatten& a, const Flatten& b ) { return !(a == b); } template Flatten makeFlatten( OuterIterator outerIterator, OuterIterator outerEnd ) { return Flatten(outerIterator, outerEnd); } /// As flatten(range(begin, end)). template Range> flatten( OuterIterator outerBegin, OuterIterator outerEnd ) { return range( makeFlatten(outerBegin, outerEnd), makeFlatten(outerEnd, outerEnd) ); } /// Constructs a range of the union of all (inner) ranges in outerRange. /// /// Example: /// std::vector> v(3); /// v[0].push_back(1); /// v[2].push_back(2); /// v[2].push_back(3); /// for (const auto& i : flatten(v)) /// std::cout << i << ' '; /// /// The output is "1 2 3 "; template auto flatten( OuterRange&& outerRange ) -> decltype(flatten(std::begin(outerRange), std::end(outerRange))) { return flatten(std::begin(outerRange), std::end(outerRange)); } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/RawVector.hpp000077500000000000000000000203271311555162500211320ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_RAW_VECTOR_GUARD #define MATHICGB_RAW_VECTOR_GUARD #include #include #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// RawVector mimics std::vector except that it does not do memory management. /// So you can directly access the pointers to memory and you can replace them /// with any other pointers that you need to. /// /// Warning: RawVector is called raw because it does not allocate any memory, /// so it is an error to insert elements that there is not enough space for - /// you need to make sure ahead of time that there is enough space. /// /// This class makes it possible to have a lot of the convenience of the /// std::vector interface even in places where std::vector cannot be used /// because of a need for manual memory management. template class RawVector { public: typedef T& reference; typedef const T& const_reference; typedef T* iterator; typedef const T* const_iterator; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; /// Initializes to the null state. RawVector(): mBegin(0), mEnd(0), mCapacityEnd(0) {} /// Copies the pointers from v. It is a shallow copy. RawVector(const RawVector& v): mBegin(v.mBegin), mEnd(v.mEnd), mCapacityEnd(v.mCapacityEnd) {} /// Copies the pointers from v. It is a shallow copy. Sets v to a null state. RawVector(RawVector&& v): mBegin(v.mBegin), mEnd(v.mEnd), mCapacityEnd(v.mCapacityEnd) { v.releaseMemory(); } RawVector(pointer begin, pointer end): mBegin(begin), mEnd(end), mCapacityEnd(end) {} RawVector(pointer begin, pointer end, pointer capacityEnd): mBegin(begin), mEnd(end), mCapacityEnd(capacityEnd) {} /// As clear() --- does not free memory. ~RawVector() { clear(); } /// There is no operator== to avoid confusion about whether it compares /// pointers or contents. Instead, there is this. bool contentsEqual(const RawVector& v) const { return std::equal(begin(), end(), v.begin()); } /// Copies the pointers from v. It is a shallow copy. RawVector& operator=(const RawVector& v) { mBegin = v.mBegin; mEnd = v.mEnd; mCapacityEnd = v.mCapacityEnd; return *this; } /// Copies the pointers from v. It is a shallow copy. Sets v to the null state. RawVector& operator=(RawVector&& v) { mBegin = v.mBegin; mEnd = v.mEnd; mCapacityEnd = v.mCapacityEnd; v.releaseMemory(); return *this; } iterator begin() {return mBegin;} const_iterator begin() const {return mBegin;} iterator end() {return mEnd;} const_iterator end() const {return mEnd;} reverse_iterator rbegin() {return reverse_iterator(end());} const_reverse_iterator rbegin() const {return const_reverse_iterator(end());} reverse_iterator rend() {return reverse_iterator(begin());} const_reverse_iterator rend() const {return const_reverse_iterator(begin());} size_type size() const {return mEnd - mBegin;} size_type max_size() const {return std::numeric_limits::max();} /// There must be enough capacity for the new size. void resize(const size_type newSize) { MATHICGB_ASSERT(newSize <= capacity()); while (newSize > size()) { new (mEnd) T(); ++mEnd; } while (newSize < size()) { --mEnd; mEnd->~T(); } MATHICGB_ASSERT(newSize == size()); } size_type capacity() const {return mCapacityEnd - mBegin;} bool empty() const {return mBegin == mEnd;} reference operator[](size_type index) { MATHICGB_ASSERT(index < size()); return mBegin[index]; } const_reference operator[](size_type index) const { MATHICGB_ASSERT(index < size()); return mBegin[index]; } reference at(size_type index) { if (index >= size()) throw std::out_of_range("Invalid index in RawVector::at."); return mBegin[index]; } const_reference at(size_type index) const { if (index >= size()) throw std::out_of_range("Invalid index in RawVector::at."); return mBegin[index]; } reference front() { MATHICGB_ASSERT(!empty()); return *mBegin; } const_reference front() const { MATHICGB_ASSERT(!empty()); return *mBegin; } reference back() { MATHICGB_ASSERT(!empty()); return *(mEnd - 1); } const_reference back() const { MATHICGB_ASSERT(!empty()); return *(mEnd - 1); } size_t memoryUse() const { return capacity() * sizeof(value_type); } size_t memoryUseTrimmed() const { return size() * sizeof(value_type); } /// There must be enough capacity for the new size. template void rawAssign(Iter begin, Iter end) { const size_t count = std::distance(begin, end); MATHICGB_ASSERT(count <= capacity()); if (count > size()) resize(count); std::copy(begin, end, mBegin); } /// There must be enough capacity for the new size. void rawAssign(size_type count, const T& t) { MATHICGB_ASSERT(count <= capacity()); if (count > size()) resize(count); std::fill_n(begin(), count, t); } /// There must be enough capacity for the new size. This is why there is no /// push_back and only a rawPushBack --- to remind you of the changed /// contract. void rawPushBack(const T& t) { MATHICGB_ASSERT(size() < capacity()); new (mEnd) T(t); ++mEnd; } void pop_back() { MATHICGB_ASSERT(!empty()); mEnd->~T(); --mEnd; } void swap(RawVector& v) { std::swap(mBegin, v.mBegin); std::swap(mEnd, v.mEnd); std::swap(mCapacityEnd, v.mCapacityEnd); } void clear() { while (!empty()) pop_back(); } // **** Extra functionality not available on std::vector // memcpy onto the end of the vector. void memcpy(const T* from, size_t countOfT) { MATHICGB_ASSERT(countOfT <= capacityToGo()); std::memcpy(mEnd, from, countOfT * sizeof(T)); mEnd += countOfT; } /// Unused capacity. size_t capacityToGo() const { return mCapacityEnd - mEnd; } /// Returns true if there is no more capacity left. That is, if /// capacity() == size(). bool atCapacity() const { return mEnd == mCapacityEnd; } /// Sets this object to its null state without destructing memory. Returns /// a pointer to the previous beginning of the buffer. pointer releaseMemory() { const auto oldBegin = mBegin; mBegin = 0; mEnd = 0; mCapacityEnd = 0; return oldBegin; } /// Takes over the new memory that is passed in, copies the old values to the /// new memory and destructs the old values. Returns a pointer to the previous /// beginning of the buffer. pointer setMemoryAndCopy( pointer begin, pointer capacityEnd ) { MATHICGB_ASSERT(size() <= static_cast(std::distance(begin, capacityEnd))); const auto oldBegin = mBegin; const auto end = std::copy(mBegin, mEnd, begin); *this = RawVector(begin, end, capacityEnd); return oldBegin; } /// Takes over the new memory that is passed in without destructing memory. /// Returns a pointer to the previous beginning of the buffer. pointer releaseAndSetMemory( pointer begin, pointer end, pointer capacityEnd ) { const auto oldBegin = mBegin; mBegin = begin; mEnd = end; mCapacityEnd = capacityEnd; return oldBegin; } /// Destructs memory and then takes over the new memory that is passed in. /// Does not deallocate the backing memory. Returns a pointer to the previous /// beginning of the buffer. pointer clearAndSetMemory( pointer begin, pointer end, pointer capacityEnd ) { clear(); const auto oldBegin = mBegin; mBegin = begin; mEnd = end; mCapacityEnd = capacityEnd; return oldBegin; } private: T* mBegin; T* mEnd; T* mCapacityEnd; }; MATHICGB_NAMESPACE_END namespace std { template void swap(mgb::RawVector& a, mgb::RawVector& b) { a.swap(b); } } #endif mathicgb-master/src/mathicgb/Reducer.cpp000077500000000000000000000076001311555162500206010ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "Reducer.hpp" #include "ReducerPack.hpp" #include "ReducerNoDedup.hpp" #include "ReducerPackDedup.hpp" #include "ReducerDedup.hpp" #include "ReducerHash.hpp" #include "ReducerHashPack.hpp" #include "F4Reducer.hpp" #include "SigPolyBasis.hpp" #include #include MATHICGB_NAMESPACE_BEGIN // Calling these dummy methods from the various reducer file headers ensures // that those translation units are registered as necessary. Without this, // they will not be linked in, because apparently the linker does not consider // the presense of global object constructors as a reason to include a // translation unit into the library. It will simply note that no other // translation unit has a dependency on anything in that translation unit // and then not include it in the library. This was wonderful to diagnose. void dummyLinkerFix() { reducerPackDependency(); reducerNoDedupDependency(); reducerPackDedupDependency(); reducerDedupDependency(); reducerHashDependency(); reducerHashPackDependency(); f4ReducerDependency(); } Reducer::~Reducer() { // Has to be called somewhere or GCC will eliminate it. dummyLinkerFix(); } /// Vector that stores the registered reducer typers. This has to be a /// function rather than just a naked object to ensure that the object /// gets initialized before it is used. std::vector& reducerTypes() { static std::vector types; return types; } Reducer::Registration::Registration( const char* name, ReducerType id, std::unique_ptr (*create)(const PolyRing&) ): mName(name), mId(id), mCreate(create) { reducerTypes().push_back(this); } std::unique_ptr Reducer::makeReducer( ReducerType type, PolyRing const& ring ) { std::unique_ptr reducer = makeReducerNullOnUnknown(type, ring); if (reducer.get() == 0) { std::ostringstream error; error << "Unknown or unimplemented reducer type " << type << ".\n"; throw std::runtime_error(error.str()); } return reducer; } std::unique_ptr Reducer::makeReducerNullOnUnknown( ReducerType type, PolyRing const& ring ) { for (const auto& r : reducerTypes()) { if (type == r->mId) return r->mCreate(ring); } return nullptr; } Reducer::ReducerType Reducer::reducerType(int type) { switch (type) { case 7: return Reducer_TourTree_NoDedup; case 8: return Reducer_TourTree_Dedup; case 9: return Reducer_TourTree_Hashed; case 10: return Reducer_TourTree_NoDedup_Packed; case 11: return Reducer_TourTree_Dedup_Packed; case 12: return Reducer_TourTree_Hashed_Packed; case 13: return Reducer_Heap_NoDedup; case 14: return Reducer_Heap_Dedup; case 15: return Reducer_Heap_Hashed; case 16: return Reducer_Heap_NoDedup_Packed; case 17: return Reducer_Heap_Dedup_Packed; case 18: return Reducer_Heap_Hashed_Packed; case 19: return Reducer_Geobucket_NoDedup; case 20: return Reducer_Geobucket_Dedup; case 21: return Reducer_Geobucket_Hashed; case 22: return Reducer_Geobucket_NoDedup_Packed; case 23: return Reducer_Geobucket_Dedup_Packed; case 24: return Reducer_Geobucket_Hashed_Packed; case 25: return Reducer_F4_Old; case 26: return Reducer_F4_New; default: return Reducer_Geobucket_Hashed; } } void Reducer::displayReducerTypes(std::ostream& out) { mathic::ColumnPrinter pr; auto& id = pr.addColumn(false, " "); auto& desc = pr.addColumn(true, " "); auto types = reducerTypes(); auto cmp = [](const Registration* a, const Registration* b) { return a->mId < b->mId; }; std::sort(types.begin(), types.end(), cmp); for (const auto& r : types) { id << r->mId << '\n'; desc << r->mName << '\n'; } out << "Reducer types:\n" << pr; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/Reducer.hpp000077500000000000000000000120741311555162500206070ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_GUARD #define MATHICGB_REDUCER_GUARD #include "PolyRing.hpp" #include #include MATHICGB_NAMESPACE_BEGIN class Poly; class SigPolyBasis; class PolyBasis; /// Abstract base class for classes that allow reduction of polynomials. /// /// @todo: consider changing name of findLeadTerm to leadTerm. class Reducer { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef coefficient Coefficient; virtual ~Reducer(); /// Returns the preferred number of reductions to do at a time. A classic /// serial reducer will have no particular benefit from doing more than /// one reduction at a time, so it should say that. A matrix-based or /// parallel reducer will have benefit from being presented with /// larger sets of reductions at a time. virtual unsigned int preferredSetSize() const = 0; virtual std::string description() const = 0; virtual size_t getMemoryUse() const = 0; // ***** Methods that do reduction /// Clasically reduces poly by the basis elements of basis. The reduction /// is classic in that no signatures are taken into account. virtual std::unique_ptr classicReduce (const Poly& poly, const PolyBasis& basis) = 0; /// Clasically reduces poly by the basis elements of basis, except that the /// lead term is not reduced. The reduction is classic in that no signatures /// are taken into account. virtual std::unique_ptr classicTailReduce (const Poly& poly, const PolyBasis& basis) = 0; /// Clasically reduces the S-polynomial between a and b. virtual std::unique_ptr classicReduceSPoly (const Poly& a, const Poly& b, const PolyBasis& basis) = 0; /// Clasically reduces the S-polynomial of these pairs. May or may /// not also interreduce these to some extent. Polynomials that are /// reduced to zero are not put into reducedOut. virtual void classicReduceSPolySet( std::vector >& spairs, const PolyBasis& basis, std::vector >& reducedOut ) = 0; /// Clasically reduces the passed-in polynomials of these pairs. May /// or may not also interreduce these to some extent. Polynomials /// that are reduced to zero are not put into reducedOut. virtual void classicReducePolySet( const std::vector >& polys, const PolyBasis& basis, std::vector >& reducedOut ) = 0; /// Regular reduce multiple*basisElement in signature sig by the /// basis elements in basis. Returns null (0) if multiple*basisElement /// is not regular top reducible -- this indicates a singular /// reduction. virtual std::unique_ptr regularReduce( ConstMonoRef sig, ConstMonoRef multiple, size_t basisElement, const SigPolyBasis& basis ) = 0; /// Sets how many bytes of memory to increase the memory use by /// at a time - if such a thing is appropriate for the reducer. virtual void setMemoryQuantum(size_t quantum) = 0; // ***** Kinds of reducers and creating a Reducer enum ReducerType { Reducer_TourTree_NoDedup = 7, Reducer_TourTree_Dedup, Reducer_TourTree_Hashed, Reducer_TourTree_NoDedup_Packed, Reducer_TourTree_Dedup_Packed, Reducer_TourTree_Hashed_Packed, Reducer_Heap_NoDedup, Reducer_Heap_Dedup, Reducer_Heap_Hashed, Reducer_Heap_NoDedup_Packed, Reducer_Heap_Dedup_Packed, Reducer_Heap_Hashed_Packed, Reducer_Geobucket_NoDedup, Reducer_Geobucket_Dedup, Reducer_Geobucket_Hashed, Reducer_Geobucket_NoDedup_Packed, Reducer_Geobucket_Dedup_Packed, Reducer_Geobucket_Hashed_Packed, Reducer_F4_Old, Reducer_F4_New }; static std::unique_ptr makeReducer (ReducerType t, const PolyRing& ring); static std::unique_ptr makeReducerNullOnUnknown (ReducerType t, const PolyRing& ring); static ReducerType reducerType(int typ); static void displayReducerTypes(std::ostream& out); class Registration { public: Registration( const char* name, ReducerType id, std::unique_ptr (*create)(const PolyRing&) ); private: friend class Reducer; const char* mName; ReducerType mId; std::unique_ptr (*mCreate)(const PolyRing&); }; }; /// Registers a reducer type with the given name and id. The value of /// create, when executed, should be something convertible to a /// std::unique_ptr. CREATE may pick up a const PolyRing& /// by the name ring. #define MATHICGB_REGISTER_REDUCER(NAME, ID, CREATE) \ namespace { \ Reducer::Registration MATHICGB_UNIQUE(reducerRegistration) ( \ NAME, \ Reducer:: ID, \ [](const PolyRing& ring) -> std::unique_ptr { \ return CREATE; \ } \ ); \ } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ReducerDedup.cpp000066400000000000000000000112531311555162500215570ustar00rootroot00000000000000#include #include "memtailor.h" // MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ReducerDedup.hpp" #include "TypicalReducer.hpp" #include "ReducerHelper.hpp" #include #include MATHICGB_NAMESPACE_BEGIN void reducerDedupDependency() {} /// As ReducerNoDedup, except that if two like terms are compared, then /// they are removed and replaced by their sum. template class Queue> class ReducerDedup : public TypicalReducer { public: ReducerDedup(const PolyRing& R); virtual ~ReducerDedup(); virtual std::string description() const { return mQueue.getName() + "-dedup"; } virtual void insertTail(NewConstTerm multiplier, const Poly& f); virtual void insert(ConstMonoRef multiplier, const Poly& f); virtual bool leadTerm(NewConstTerm& result); virtual void removeLeadTerm(); virtual size_t getMemoryUse() const; virtual void resetReducer(); public: // This Configuration is designed to work with // mathic::TourTree, mathic::Heap, and mathic::Geobucket class Configuration : public ReducerHelper::DedupConfiguration { public: typedef NewTerm Entry; Configuration(const PolyRing& ring): DedupConfiguration(ring) {} CompareResult compare(const Entry& a, const Entry& b) const { return ring().monoid().compare(*a.mono, *b.mono); } Entry deduplicate(Entry a, Entry b) const { // change a.coeff, and free b.monom ring().coefficientAddTo(a.coef, b.coef); ring().monoid().freeRaw(*b.mono); return a; } }; private: const PolyRing& mRing; NewTerm mLeadTerm; bool mLeadTermKnown; Queue mQueue; }; template class Q> ReducerDedup::ReducerDedup(const PolyRing& ring): mRing(ring), mLeadTermKnown(false), mQueue(Configuration(ring)) { mLeadTerm.mono = mRing.monoid().alloc().release(); } template class Q> ReducerDedup::~ReducerDedup() { resetReducer(); mRing.monoid().freeRaw(*mLeadTerm.mono); } template class Q> void ReducerDedup::insertTail(NewConstTerm multiple, const Poly& poly) { if (poly.termCount() <= 1) return; mLeadTermKnown = false; auto it = poly.begin(); const auto end = poly.end(); for (++it; it != end; ++it) { NewTerm t; t.mono = mRing.monoid().alloc().release(); mRing.monoid().multiply(*multiple.mono, it.mono(), *t.mono); mRing.coefficientMult(multiple.coef, it.coef(), t.coef); mQueue.push(t); } } template class Q> void ReducerDedup::insert(ConstMonoRef multiple, const Poly& poly) { if (poly.isZero()) return; mLeadTermKnown = false; const auto end = poly.end(); for (auto it = poly.begin(); it != end; ++it) { NewTerm t = {it.coef(), mRing.monoid().alloc().release()}; mRing.monoid().multiply(multiple, it.mono(), *t.mono); mQueue.push(t); } } template class Q> bool ReducerDedup::leadTerm(NewConstTerm& result) { if (!mLeadTermKnown) { do { if (mQueue.empty()) return false; mLeadTerm = mQueue.top(); mQueue.pop(); while (!mQueue.empty()) { auto entry = mQueue.top(); if (!mRing.monoid().equal(*entry.mono, *mLeadTerm.mono)) break; mRing.coefficientAddTo(mLeadTerm.coef, entry.coef); mRing.monoid().freeRaw(*entry.mono); mQueue.pop(); } } while (mRing.coefficientIsZero(mLeadTerm.coef)); mLeadTermKnown = true; } result = mLeadTerm; return true; } template class Q> void ReducerDedup::removeLeadTerm() { if (!mLeadTermKnown) { NewConstTerm dummy; leadTerm(dummy); } mLeadTermKnown = false; } template class Q> void ReducerDedup::resetReducer() { class MonomialFree { public: MonomialFree(const PolyRing& ring): mRing(ring) {} bool proceed(NewTerm entry) { mRing.monoid().freeRaw(*entry.mono); return true; } private: const PolyRing& mRing; }; MonomialFree freeer(mRing); mQueue.forAll(freeer); mQueue.clear(); } template class Q> size_t ReducerDedup::getMemoryUse() const { return TypicalReducer::getMemoryUse() + mQueue.getMemoryUse(); } MATHICGB_REGISTER_REDUCER( "TourDedup", Reducer_TourTree_Dedup, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "HeapDedup", Reducer_Heap_Dedup, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "GeoDedup", Reducer_Geobucket_Dedup, make_unique>(ring) ); MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ReducerDedup.hpp000077500000000000000000000010331311555162500215620ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_DEDUP_GUARD #define MATHICGB_REDUCER_DEDUP_GUARD MATHICGB_NAMESPACE_BEGIN // This translation unit has to expose something that is needed elsewhere. // Otherwise, the compiler will think it is not needed and exclude the // whole thing, despite there being important global objects in the .cpp file. void reducerDedupDependency(); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ReducerHash.cpp000066400000000000000000000076001311555162500214020ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ReducerHash.hpp" #include "TypicalReducer.hpp" #include "ReducerHelper.hpp" #include "PolyHashTable.hpp" #include #include MATHICGB_NAMESPACE_BEGIN void reducerHashDependency() {} /// The simplest reducer using a hashtable. All terms are in the hash table /// and in the queue. There are no duplicates as new terms are looked up in /// the hash table before insertion into the queue. The coefficient is /// stored in the hash table. template class Queue> class ReducerHash : public TypicalReducer { public: ReducerHash(const PolyRing &ring); virtual std::string description() const { return mQueue.getName() + "-hashed"; } void insertTail(NewConstTerm multiplier, const Poly& f); void insert(ConstMonoRef multiplier, const Poly& f); virtual bool leadTerm(NewConstTerm& result); void removeLeadTerm(); size_t getMemoryUse() const; void resetReducer(); public: class Configuration : public ReducerHelper::PlainConfiguration { public: typedef PolyHashTable::Node* Entry; Configuration(const PolyRing& ring): PlainConfiguration(ring) {} CompareResult compare(const Entry& a, const Entry& b) const { return ring().monoid().lessThan(a->mono(), b->mono()); } }; private: mutable std::vector mNodesTmp; const PolyRing &mRing; PolyHashTable mHashTable; Queue mQueue; }; template class Q> ReducerHash::ReducerHash(const PolyRing &ring): mRing(ring), mHashTable(ring), mQueue(Configuration(ring)) {} template class Q> void ReducerHash::insertTail(NewConstTerm multiplier, const Poly& f) { if (f.termCount() <= 1) return; mNodesTmp.clear(); auto it = f.begin(); const auto end = f.end(); for (++it; it != end; ++it) { auto p = mHashTable.insertProduct(*it, multiplier); if (p.second) mNodesTmp.emplace_back(p.first); } if (!mNodesTmp.empty()) mQueue.push(mNodesTmp.begin(), mNodesTmp.end()); } template class Q> void ReducerHash::insert(ConstMonoRef multiplier, const Poly& f) { mNodesTmp.clear(); const auto end = f.end(); for (auto it = f.begin(); it != end; ++it) { auto p = mHashTable.insertProduct(it.mono(), multiplier, it.coef()); if (p.second) mNodesTmp.emplace_back(p.first); } if (!mNodesTmp.empty()) mQueue.push(mNodesTmp.begin(), mNodesTmp.end()); } template class Q> bool ReducerHash::leadTerm(NewConstTerm& result) { while (!mQueue.empty()) { const auto top = mQueue.top(); if (!mRing.coefficientIsZero(top->value())) { result.coef = top->value(); result.mono = top->mono().ptr(); return true; } mQueue.pop(); mHashTable.remove(top); } return false; } template class Q> void ReducerHash::removeLeadTerm() { const auto top = mQueue.top(); mQueue.pop(); mHashTable.remove(top); } template class Q> void ReducerHash::resetReducer() { while (!mQueue.empty()) { const auto top = mQueue.top(); mQueue.pop(); mHashTable.remove(top); } mHashTable.clear(); } template class Q> size_t ReducerHash::getMemoryUse() const { size_t result = TypicalReducer::getMemoryUse(); result += mHashTable.getMemoryUse(); result += mQueue.getMemoryUse(); return result; } MATHICGB_REGISTER_REDUCER( "TourHash", Reducer_TourTree_Hashed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "HeapHash", Reducer_Heap_Hashed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "GeoHash", Reducer_Geobucket_Hashed, make_unique>(ring) ); MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ReducerHash.hpp000077500000000000000000000010301311555162500214010ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_HASH_GUARD #define MATHICGB_REDUCER_HASH_GUARD MATHICGB_NAMESPACE_BEGIN // This translation unit has to expose something that is needed elsewhere. // Otherwise, the compiler will think it is not needed and exclude the // whole thing, despite there being important global objects in the .cpp file. void reducerHashDependency(); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ReducerHashPack.cpp000066400000000000000000000161031311555162500221770ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ReducerHashPack.hpp" #include "TypicalReducer.hpp" #include "ReducerHelper.hpp" #include "PolyHashTable.hpp" #include #include MATHICGB_NAMESPACE_BEGIN void reducerHashPackDependency() {} /// A combination of ReducerHash and ReducerPack. Each entry in the queue /// corresponds to a term (times a multiplier) of a polynomial. When such a /// term is taken off the queue, we advance it to the next term of the /// corresponding polynomial and push that back into the queue. Each entry /// in the queue is also associated to a hash table entry, where the /// data is stored - the entries in the queue are just pointers into /// hash table nodes. There are no like terms to add up in the queue, since /// the hash table identifies such before insertion into the queue. /// /// There is no need for the complexity of chaining as in ReducerPackDedup, /// since we simply keep advancing through the terms in a polynomial until /// there are no more terms or we get a term that is unlike any other term /// in the queue. We could have stored a list of like terms for each /// entry in the queue as in ReducerPackDedup, which might reduce the size of /// the queue, but this is a good compromise that leads to simpler code. template class Queue> class ReducerHashPack : public TypicalReducer { public: ReducerHashPack(const PolyRing& R); virtual ~ReducerHashPack(); virtual std::string description() const { return mQueue.getName() + "-hashed-packed"; } virtual void insertTail(NewConstTerm multiplier, const Poly& f); virtual void insert(ConstMonoRef multiplier, const Poly& f); virtual bool leadTerm(NewConstTerm& result); virtual void removeLeadTerm(); virtual size_t getMemoryUse() const; virtual void resetReducer(); private: // Represents a term multiple of a polynomial, // together with a current term of the multiple. struct MultipleWithPos { MultipleWithPos(const Poly& poly, NewConstTerm multiple); Poly::ConstTermIterator pos; const Poly::ConstTermIterator end; NewTerm multiple; PolyHashTable::Node* node; void destroy(const PolyRing& ring); }; class Configuration : public ReducerHelper::PlainConfiguration { public: typedef MultipleWithPos* Entry; Configuration(const PolyRing& ring) : PlainConfiguration(ring) {} CompareResult compare(const Entry& a, const Entry& b) const { return ring().monoid().lessThan(a->node->mono(), b->node->mono()); } }; void insertEntry(MultipleWithPos* entry); const PolyRing& mRing; Queue mQueue; PolyHashTable mHashTable; memt::BufferPool mPool; }; template class Q> ReducerHashPack::ReducerHashPack(const PolyRing& ring): mRing(ring), mQueue(Configuration(ring)), mHashTable(ring), mPool(sizeof(MultipleWithPos)) {} template class Q> ReducerHashPack::~ReducerHashPack() { resetReducer(); } template class Q> void ReducerHashPack::insertTail(NewConstTerm multiple, const Poly& poly) { MATHICGB_ASSERT(&poly.ring() == &mRing); if (poly.termCount() <= 1) return; auto entry = new (mPool.alloc()) MultipleWithPos(poly, multiple); ++entry->pos; insertEntry(entry); } template class Q> void ReducerHashPack::insert(ConstMonoRef multiple, const Poly& poly) { MATHICGB_ASSERT(&poly.ring() == &mRing); if (poly.isZero()) return; NewConstTerm termMultiple = {1, multiple.ptr()}; insertEntry(new (mPool.alloc()) MultipleWithPos(poly, termMultiple)); } template class Q> ReducerHashPack::MultipleWithPos::MultipleWithPos( const Poly& poly, NewConstTerm multipleParam ): pos(poly.begin()), end(poly.end()), node(0) { multiple.mono = poly.ring().monoid().alloc().release(); poly.ring().monoid().copy(*multipleParam.mono, *multiple.mono); multiple.coef = multipleParam.coef; } template class Q> void ReducerHashPack::MultipleWithPos::destroy(const PolyRing& ring) { ring.monoid().freeRaw(*multiple.mono); // Call the destructor to destruct the iterators into std::vector. // In debug mode MSVC puts those in a linked list and the destructor // has to be called since it takes an iterator off the list. There were // memory corruption problems in debug mode on MSVC before doing this. this->~MultipleWithPos(); } template class Q> bool ReducerHashPack::leadTerm(NewConstTerm& result) { while (!mQueue.empty()) { auto entry = mQueue.top(); MATHICGB_ASSERT(entry != nullptr); if (!mRing.coefficientIsZero(entry->node->value())) { result.coef = entry->node->value(); result.mono = entry->node->mono().ptr(); return true; } removeLeadTerm(); } return false; } template class Q> void ReducerHashPack::removeLeadTerm() { MATHICGB_ASSERT(!mQueue.empty()); auto entry = mQueue.top(); MATHICGB_ASSERT(entry != 0); // remove node from hash table first since we are going to be changing // the monomial after this, and if we do that before the hash value will // change. That might prompt an assert inside the hash table. mHashTable.remove(entry->node); MATHICGB_ASSERT(entry->pos != entry->end); while (true) { ++entry->pos; if (entry->pos == entry->end) { mQueue.pop(); entry->destroy(mRing); mPool.free(entry); break; } const auto p = mHashTable.insertProduct(entry->multiple, *entry->pos); if (p.second) { entry->node = p.first; mQueue.decreaseTop(entry); break; } } } template class Q> void ReducerHashPack::insertEntry(MultipleWithPos* entry) { MATHICGB_ASSERT(entry != 0); for (; entry->pos != entry->end; ++entry->pos) { const auto p = mHashTable.insertProduct(entry->multiple, *entry->pos); if (p.second) { entry->node = p.first; mQueue.push(entry); return; } } entry->destroy(mRing); mPool.free(entry); } template class Q> void ReducerHashPack::resetReducer() { class MonomialFree { public: MonomialFree(const PolyRing& ring): mRing(ring) {} bool proceed(MultipleWithPos* entry) { entry->destroy(mRing); return true; } private: const PolyRing& mRing; }; MonomialFree freeer(mRing); mQueue.forAll(freeer); mQueue.clear(); mHashTable.clear(); } template class Q> size_t ReducerHashPack::getMemoryUse() const { return mQueue.getMemoryUse() + mPool.getMemoryUse() + mHashTable.getMemoryUse(); } MATHICGB_REGISTER_REDUCER( "TourHashPack", Reducer_TourTree_Hashed_Packed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "HeapHashPack", Reducer_Heap_Hashed_Packed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "GeoHashPack", Reducer_Geobucket_Hashed_Packed, make_unique>(ring) ); MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ReducerHashPack.hpp000077500000000000000000000010461311555162500222070ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_HASH_PACK_GUARD #define MATHICGB_REDUCER_HASH_PACK_GUARD MATHICGB_NAMESPACE_BEGIN // This translation unit has to expose something that is needed elsewhere. // Otherwise, the compiler will think it is not needed and exclude the // whole thing, despite there being important global objects in the .cpp file. void reducerHashPackDependency(); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ReducerHelper.hpp000077500000000000000000000055451311555162500217540ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_HELPER_GUARD #define MATHICGB_REDUCER_HELPER_GUARD // This namespace contains functions and classees that are useful for // writing subclasses of Reducer. #include "PolyRing.hpp" MATHICGB_NAMESPACE_BEGIN namespace ReducerHelper { // ************** Configurations ********************** // Common base class for the configurations offered here. // The configurations are designed to work with // mathic::TourTree, mathic::Heap and mathic::Geobucket. class ConfigurationBasics { public: ConfigurationBasics(const PolyRing& ring): mRing(ring) {} const PolyRing& ring() const {return mRing;} // Special fields for TourTree and Heap static const bool fastIndex = true; // Special fields for Geobuckets: static const size_t geoBase = 4; static const size_t minBucketSize = 8; static const bool minBucketBinarySearch = false; static const bool trackFront = true; static const bool premerge = false; static const bool collectMax = false; static const int bucketStorage = 1; static const size_t insertFactor = 1; private: const PolyRing& mRing; }; // Base class for a configuration with deduplication turned off. // This cannot be a template since then all the names would be hidden // in any subclasses. class PlainConfiguration : public ConfigurationBasics { public: PlainConfiguration(const PolyRing& ring): ConfigurationBasics(ring) {} static const bool supportDeduplication = false; typedef bool CompareResult; bool cmpLessThan(bool r) const {return r;} // These last two members are not supposed to be called. // The dummy deduplicate function has to be a template since we do not // know what type Entry is. template Entry deduplicate(Entry a, Entry b) const { MATHICGB_ASSERT(false); return a; } bool cmpEqual(bool) const { MATHICGB_ASSERT(false); return false; } }; // Base class for a configuration with deduplication turned on. // This cannot be a template since then all the names would be hidden // in any subclasses. class DedupConfiguration : public ConfigurationBasics { public: DedupConfiguration(const PolyRing& ring): ConfigurationBasics(ring) {} static const bool supportDeduplication = true; typedef int CompareResult; bool cmpLessThan(int r) const {return r == LT;} bool cmpEqual(int r) const {return r == EQ;} }; // ************** Utility functions ********************** inline const_term allocTermCopy(const PolyRing& ring, const_term term) { monomial mono = ring.allocMonomial(); ring.monomialCopy(term.monom, mono); return const_term(term.coeff, mono); } } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ReducerNoDedup.cpp000066400000000000000000000113051311555162500220520ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ReducerNoDedup.hpp" #include "TypicalReducer.hpp" #include "ReducerHelper.hpp" #include #include MATHICGB_NAMESPACE_BEGIN void reducerNoDedupDependency() {} /// The most straight forward of the reducers. Simply keep a priority queue /// with all the pending terms. If two like monomials are compared in the /// queue, they are not combined - both stay in the queue. The sum of like /// terms is only taken at the end, when the leading term and its /// coefficient is determined. template class Queue> class ReducerNoDedup : public TypicalReducer { public: ReducerNoDedup(const PolyRing& R); virtual ~ReducerNoDedup(); virtual std::string description() const { return mQueue.getName() + "-nodedup"; } virtual void insertTail(NewConstTerm multiplier, const Poly& f); virtual void insert(ConstMonoRef multiplier, const Poly& f); virtual bool leadTerm(NewConstTerm& result); virtual void removeLeadTerm(); virtual size_t getMemoryUse() const; virtual void resetReducer(); private: // This Configuration is designed to work with // mathic::TourTree, mathic::Heap, and mathic::Geobucket class Configuration : public ReducerHelper::PlainConfiguration { public: typedef NewTerm Entry; Configuration(const PolyRing& ring): PlainConfiguration(ring) {} CompareResult compare(const Entry& a, const Entry& b) const { return ring().monoid().lessThan(*a.mono, *b.mono); } }; const PolyRing& mRing; NewTerm mLeadTerm; bool mLeadTermKnown; Queue mQueue; }; template class Q> ReducerNoDedup::ReducerNoDedup(const PolyRing& ring): mRing(ring), mLeadTermKnown(false), mQueue(Configuration(ring)) { mLeadTerm.mono = mRing.monoid().alloc().release(); } template class Q> ReducerNoDedup::~ReducerNoDedup() { resetReducer(); mRing.monoid().freeRaw(*mLeadTerm.mono); } template class Q> void ReducerNoDedup::insertTail(NewConstTerm multiple, const Poly& poly) { if (poly.termCount() <= 1) return; mLeadTermKnown = false; auto it = poly.begin(); const auto end = poly.end(); for (++it; it != end; ++it) { NewTerm t; t.mono = mRing.allocMonomial(); mRing.monoid().multiply(*multiple.mono, it.mono(), *t.mono); mRing.coefficientMult(multiple.coef, it.coef(), t.coef); mQueue.push(t); } } template class Q> void ReducerNoDedup::insert(ConstMonoRef multiple, const Poly& poly) { if (poly.isZero()) return; mLeadTermKnown = false; const auto end = poly.end(); for (auto it = poly.begin(); it != end; ++it) { NewTerm t = {it.coef(), mRing.monoid().alloc().release()}; mRing.monoid().multiply(multiple, it.mono(), *t.mono); mQueue.push(t); } } template class Q> bool ReducerNoDedup::leadTerm(NewConstTerm& result) { if (!mLeadTermKnown) { do { if (mQueue.empty()) return false; mLeadTerm = mQueue.top(); mQueue.pop(); while (true) { if (mQueue.empty()) break; auto entry = mQueue.top(); if (!mRing.monoid().equal(*entry.mono, *mLeadTerm.mono)) break; mRing.coefficientAddTo(mLeadTerm.coef, entry.coef); mRing.monoid().freeRaw(*entry.mono); mQueue.pop(); } } while (mRing.coefficientIsZero(mLeadTerm.coef)); mLeadTermKnown = true; } result = mLeadTerm; return true; } template class Q> void ReducerNoDedup::removeLeadTerm() { if (!mLeadTermKnown) { NewConstTerm dummy; leadTerm(dummy); } mLeadTermKnown = false; } template class Q> void ReducerNoDedup::resetReducer() { class MonomialFree { public: MonomialFree(const PolyRing& ring): mRing(ring) {} bool proceed(NewTerm entry) { mRing.monoid().freeRaw(*entry.mono); return true; } private: const PolyRing& mRing; }; MonomialFree freeer(mRing); mQueue.forAll(freeer); mQueue.clear(); } template class Q> size_t ReducerNoDedup::getMemoryUse() const { return TypicalReducer::getMemoryUse() + mQueue.getMemoryUse(); } MATHICGB_REGISTER_REDUCER( "TourNoDedup", Reducer_TourTree_NoDedup, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "HeapNoDedup", Reducer_Heap_NoDedup, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "GeoNoDedup", Reducer_Geobucket_NoDedup, make_unique>(ring) ); MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ReducerNoDedup.hpp000077500000000000000000000010421311555162500220570ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_NO_DEDUP_GUARD #define MATHICGB_REDUCER_NO_DEDUP_GUARD MATHICGB_NAMESPACE_BEGIN // This translation unit has to expose something that is needed elsewhere. // Otherwise, the compiler will think it is not needed and exclude the // whole thing, despite there being important global objects in the .cpp file. void reducerNoDedupDependency(); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ReducerPack.cpp000066400000000000000000000154401311555162500213760ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ReducerPack.hpp" #include "TypicalReducer.hpp" #include "ReducerHelper.hpp" #include #include MATHICGB_NAMESPACE_BEGIN void reducerPackDependency() {} /// Keep a priority queue with entries that represent a term of a polynomial /// times a multiplier. When an entry is popped, move on to the next /// term of the polynomial, if any, and push that back into the queue. The /// idea is that this reduces the number of elements in the queue, leading /// to faster queue operations. Memory is also saved compared to expanding /// each new polynomial with n terms into n entries in the queue. template class Queue> class ReducerPack : public TypicalReducer { public: ReducerPack(const PolyRing& ring): mRing(ring), mLeadTermKnown(false), mQueue(Configuration(ring)), mPool(sizeof(MultipleWithPos)) { mLeadTerm.mono = mRing.monoid().alloc().release(); } virtual ~ReducerPack() { resetReducer(); mRing.monoid().freeRaw(*mLeadTerm.mono); } virtual std::string description() const { return mQueue.getName() + "-packed"; } virtual void insertTail(NewConstTerm multiplier, const Poly& f); virtual void insert(ConstMonoRef multiplier, const Poly& f); virtual bool leadTerm(NewConstTerm& result); virtual void removeLeadTerm(); virtual size_t getMemoryUse() const; private: virtual void resetReducer(); // Represents a term multiple of a polynomial, // together with a current term of the multiple. struct MultipleWithPos { MultipleWithPos(const Poly& poly, NewConstTerm multiple); Poly::ConstTermIterator pos; const Poly::ConstTermIterator end; NewTerm multiple; // invariant: current is the monomial product of multiple.monom // and pos.getMonomial(). MonoPtr current; // Ensures the invariant, so sets current to the product of // multiple.monom and pos.getMonomial(). void computeCurrent(const PolyRing& ring); void currentCoefficient(const PolyRing& ring, coefficient& coeff); void destroy(const PolyRing& ring); }; class Configuration : public ReducerHelper::PlainConfiguration { public: typedef MultipleWithPos* Entry; Configuration(const PolyRing& ring) : PlainConfiguration(ring) {} CompareResult compare(const Entry& a, const Entry& b) const { return ring().monoid().lessThan(*a->current, *b->current); } }; private: const PolyRing& mRing; NewTerm mLeadTerm; bool mLeadTermKnown; Queue mQueue; memt::BufferPool mPool; }; template class Q> void ReducerPack::insertTail(NewConstTerm multiple, const Poly& poly) { if (poly.termCount() <= 1) return; mLeadTermKnown = false; MultipleWithPos* entry = new (mPool.alloc()) MultipleWithPos(poly, multiple); ++entry->pos; entry->computeCurrent(poly.ring()); mQueue.push(entry); } template class Q> void ReducerPack::insert(ConstMonoRef multiple, const Poly& poly) { if (poly.isZero()) return; mLeadTermKnown = false; NewConstTerm termMultiple = {1, multiple.ptr()}; auto entry = new (mPool.alloc()) MultipleWithPos(poly, termMultiple); entry->computeCurrent(poly.ring()); mQueue.push(entry); } template class Q> ReducerPack::MultipleWithPos::MultipleWithPos( const Poly& poly, NewConstTerm multipleParam ): pos(poly.begin()), end(poly.end()), current(poly.ring().allocMonomial()) { multiple.mono = poly.ring().monoid().alloc().release(); poly.ring().monoid().copy(*multipleParam.mono, *multiple.mono); multiple.coef = multipleParam.coef; } template class Q> void ReducerPack::MultipleWithPos::computeCurrent(const PolyRing& ring) { ring.monoid().multiply(*multiple.mono, pos.mono(), *current); } template class Q> void ReducerPack::MultipleWithPos::currentCoefficient (const PolyRing& ring, coefficient& coeff) { ring.coefficientMult(multiple.coef, pos.coef(), coeff); } template class Q> void ReducerPack::MultipleWithPos::destroy(const PolyRing& ring) { ring.monoid().freeRaw(*current); ring.monoid().freeRaw(*multiple.mono); // Call the destructor to destruct the iterators into std::vector. // In debug mode MSVC puts those in a linked list and the destructor // has to be called since it takes an iterator off the list. There were // memory corruption problems in debug mode before doing this on MSVC. this->~MultipleWithPos(); } template class Q> bool ReducerPack::leadTerm(NewConstTerm& result) { if (!mLeadTermKnown) { do { if (mQueue.empty()) return false; MultipleWithPos* entry = mQueue.top(); std::swap(mLeadTerm.mono, entry->current); entry->currentCoefficient(mRing, mLeadTerm.coef); while (true) { ++entry->pos; if (entry->pos == entry->end) { mQueue.pop(); entry->destroy(mRing); mPool.free(entry); } else { entry->computeCurrent(mRing); mQueue.decreaseTop(entry); } if (mQueue.empty()) break; entry = mQueue.top(); if (!mRing.monoid().equal(*entry->current, *mLeadTerm.mono)) break; coefficient coef; entry->currentCoefficient(mRing, coef); mRing.coefficientAddTo (mLeadTerm.coef, const_cast(coef)); } } while (mRing.coefficientIsZero(mLeadTerm.coef)); } result = mLeadTerm; mLeadTermKnown = true; return true; } template class Q> void ReducerPack::removeLeadTerm() { if (!mLeadTermKnown) { NewConstTerm dummy; leadTerm(dummy); } mLeadTermKnown = false; } template class Q> void ReducerPack::resetReducer() { class MonomialFree { public: MonomialFree(const PolyRing& ring): mRing(ring) {} bool proceed(MultipleWithPos* entry) { entry->destroy(mRing); return true; } private: const PolyRing& mRing; }; MonomialFree freeer(mRing); mQueue.forAll(freeer); mQueue.clear(); } template class Q> size_t ReducerPack::getMemoryUse() const { return TypicalReducer::getMemoryUse() + mQueue.getMemoryUse() + mPool.getMemoryUse(); } MATHICGB_REGISTER_REDUCER( "TourNoDedupPack", Reducer_TourTree_NoDedup_Packed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "HeapNoDedupPack", Reducer_Heap_NoDedup_Packed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "GeoNoDedupPack", Reducer_Geobucket_NoDedup_Packed, make_unique>(ring) ); MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ReducerPack.hpp000066400000000000000000000010301311555162500213710ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_PACK_GUARD #define MATHICGB_REDUCER_PACK_GUARD MATHICGB_NAMESPACE_BEGIN // This translation unit has to expose something that is needed elsewhere. // Otherwise, the compiler will think it is not needed and exclude the // whole thing, despite there being important global objects in the .cpp file. void reducerPackDependency(); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ReducerPackDedup.cpp000066400000000000000000000230651311555162500223620ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "ReducerPackDedup.hpp" #include "TypicalReducer.hpp" #include "ReducerHelper.hpp" #include #include MATHICGB_NAMESPACE_BEGIN void reducerPackDedupDependency() {} /// As ReducerPack, with an extra feature: if two items with the same current /// monomial in the queue are compared by the queue, then combine the first /// into the second. That way, the second can be removed from the queue. /// This requires keeping a linked list with each entry of the other entries /// that have been combined into it, since we need to move on to the next term /// of all of those entries. This technique further reduces the number of /// entries in the queue. /// /// Note that the linked lists are circular to make it fast to append two /// linked lists. The trick is that you can combine two distinct circular /// lists by swapping the next pointers of any one node in the first list and /// of any one node in the second list. template class Queue> class ReducerPackDedup : public TypicalReducer { public: ReducerPackDedup(const PolyRing& ring); virtual ~ReducerPackDedup(); virtual std::string description() const { return mQueue.getName() + "-packed"; } virtual void insertTail(NewConstTerm multiplier, const Poly& f); virtual void insert(ConstMonoRef multiplier, const Poly& f); virtual bool leadTerm(NewConstTerm& result); virtual void removeLeadTerm(); virtual size_t getMemoryUse() const; virtual void resetReducer(); private: // Represents a term multiple of a polynomial, // together with a current term of the multiple. struct MultipleWithPos { MultipleWithPos(const Poly& poly, NewConstTerm multiple); Poly::ConstTermIterator pos; const Poly::ConstTermIterator end; NewTerm multiple; // invariant: current is the monomial product of multiple.monom // and pos.mono(). MonoPtr current; // Ensures the invariant, so sets current to the product of // multiple.monom and pos.mono(). void computeCurrent(const PolyRing& ring); void currentCoefficient(const PolyRing& ring, Coefficient& coeff); void addCurrentCoefficient(const PolyRing& ring, Coefficient& coeff); void destroy(const PolyRing& ring); // Points to a circular list of entries that have the same current // monomial. If no other such entries have been discovered, then // chain points to this object itself. We use a circular linked list // as those allow merging in O(1) time. MultipleWithPos* chain; void mergeChains(MultipleWithPos& entry) { // This only works if *this and entry are not already in the // same chain! std::swap(chain, entry.chain); } }; class Configuration : public ReducerHelper::DedupConfiguration { public: typedef MultipleWithPos* Entry; Configuration(const PolyRing& ring): DedupConfiguration(ring) {} CompareResult compare(const Entry& a, const Entry& b) const { return ring().monoid().compare(*a->current, *b->current); } Entry deduplicate(Entry a, Entry b) const { a->mergeChains(*b); return a; } }; private: class MonomialFree; const PolyRing& mRing; NewTerm mLeadTerm; bool mLeadTermKnown; Queue mQueue; memt::BufferPool mPool; }; template class Q> ReducerPackDedup::ReducerPackDedup(const PolyRing& ring): mRing(ring), mLeadTermKnown(false), mQueue(Configuration(ring)), mPool(sizeof(MultipleWithPos)) { mLeadTerm.mono = mRing.monoid().alloc().release(); } template class Q> ReducerPackDedup::~ReducerPackDedup() { resetReducer(); mRing.monoid().freeRaw(*mLeadTerm.mono); } template class Q> void ReducerPackDedup::insertTail(NewConstTerm multiple, const Poly& poly) { if (poly.termCount() <= 1) return; mLeadTermKnown = false; auto entry = new (mPool.alloc()) MultipleWithPos(poly, multiple); ++entry->pos; entry->computeCurrent(poly.ring()); mQueue.push(entry); } template class Q> void ReducerPackDedup::insert(ConstMonoRef multiple, const Poly& poly) { if (poly.isZero()) return; mLeadTermKnown = false; NewConstTerm termMultiple = {1, multiple.ptr()}; auto entry = new (mPool.alloc()) MultipleWithPos(poly, termMultiple); entry->computeCurrent(poly.ring()); mQueue.push(entry); } template class Q> ReducerPackDedup::MultipleWithPos::MultipleWithPos( const Poly& poly, NewConstTerm multipleParam ): pos(poly.begin()), end(poly.end()), current(poly.ring().monoid().alloc().release()), chain(this) { multiple.mono = poly.ring().monoid().alloc().release(); poly.ring().monoid().copy(*multipleParam.mono, *multiple.mono); multiple.coef = multipleParam.coef; } template class Q> void ReducerPackDedup::MultipleWithPos::computeCurrent( const PolyRing& ring ) { ring.monoid().multiply(*multiple.mono, pos.mono(), *current); } template class Q> void ReducerPackDedup::MultipleWithPos::currentCoefficient( const PolyRing& ring, Coefficient& coef ) { ring.coefficientMult(multiple.coef, pos.coef(), coef); } template class Q> void ReducerPackDedup::MultipleWithPos::addCurrentCoefficient( const PolyRing& ring, Coefficient& coeff ) { Coefficient tmp; ring.coefficientMult(multiple.coef, pos.coef(), tmp); ring.coefficientAddTo(coeff, tmp); } template class Q> void ReducerPackDedup::MultipleWithPos::destroy(const PolyRing& ring) { MultipleWithPos* entry = this; do { ring.monoid().freeRaw(*entry->current); ring.monoid().freeRaw(*entry->multiple.mono); MultipleWithPos* next = entry->chain; MATHICGB_ASSERT(next != 0); // Call the destructor to destruct the iterators into std::vector. // In debug mode MSVC puts those in a linked list and the destructor // has to be called since it takes an iterator off the list. There were // memory corruption problems in debug mode on MSVC before doing this. entry->~MultipleWithPos(); entry = next; } while (entry != this); } template class Q> bool ReducerPackDedup::leadTerm(NewConstTerm& result) { if (!mLeadTermKnown) { do { if (mQueue.empty()) return false; auto entry = mQueue.top(); entry->currentCoefficient(mRing, mLeadTerm.coef); while (true) { // store the chained elements const auto chainBegin = entry->chain; const auto chainEnd = entry; // the list is circular entry->chain = entry; // detach any chained elements // handle the entry itself std::swap(mLeadTerm.mono, entry->current); ++entry->pos; if (entry->pos == entry->end) { mQueue.pop(); entry->destroy(mRing); mPool.free(entry); } else { entry->computeCurrent(mRing); // Inserted spans must be in descending order MATHICGB_ASSERT(mQueue.getConfiguration().ring(). monoid().lessThan(*entry->current, *mLeadTerm.mono)); mQueue.decreaseTop(entry); } // handle any chained elements auto chain = chainBegin; while (chain != chainEnd) { MATHICGB_ASSERT(chain != 0); MATHICGB_ASSERT(mRing.monoid().equal(*chain->current, *mLeadTerm.mono)); const auto next = chain->chain; chain->chain = chain; // detach from remaining chained elements chain->addCurrentCoefficient(mRing, mLeadTerm.coef); ++chain->pos; if (chain->pos == chain->end) { chain->destroy(mRing); mPool.free(chain); } else { chain->computeCurrent(mRing); // Inserted spans must be in descending order MATHICGB_ASSERT(mQueue.getConfiguration().ring(). monoid().lessThan(*chain->current, *mLeadTerm.mono)); mQueue.push(chain); } chain = next; } if (mQueue.empty()) break; entry = mQueue.top(); if (!mRing.monoid().equal(*entry->current, *mLeadTerm.mono)) break; entry->addCurrentCoefficient(mRing, mLeadTerm.coef); } } while (mRing.coefficientIsZero(mLeadTerm.coef)); mLeadTermKnown = true; } result = mLeadTerm; return true; } template class Q> void ReducerPackDedup::removeLeadTerm() { if (!mLeadTermKnown) { NewConstTerm dummy; leadTerm(dummy); } mLeadTermKnown = false; } template class Q> void ReducerPackDedup::resetReducer() { class MonomialFree { public: MonomialFree(const PolyRing& ring): mRing(ring) {} bool proceed(MultipleWithPos* entry) { entry->destroy(mRing); return true; } private: const PolyRing& mRing; }; MonomialFree freeer(mRing); mQueue.forAll(freeer); mQueue.clear(); } template class Q> size_t ReducerPackDedup::getMemoryUse() const { return TypicalReducer::getMemoryUse() + mQueue.getMemoryUse() + mPool.getMemoryUse(); } MATHICGB_REGISTER_REDUCER( "TourDedupPack", Reducer_TourTree_Dedup_Packed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "HeapDedupPack", Reducer_Heap_Dedup_Packed, make_unique>(ring) ); MATHICGB_REGISTER_REDUCER( "GeoDedupPack", Reducer_Geobucket_Dedup_Packed, make_unique>(ring) ); MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/ReducerPackDedup.hpp000077500000000000000000000010511311555162500223610ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_REDUCER_PACK_DEDUP_GUARD #define MATHICGB_REDUCER_PACK_DEDUP_GUARD MATHICGB_NAMESPACE_BEGIN // This translation unit has to expose something that is needed elsewhere. // Otherwise, the compiler will think it is not needed and exclude the // whole thing, despite there being important global objects in the .cpp file. void reducerPackDedupDependency(); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/SPairs.cpp000077500000000000000000000551051311555162500204140ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "SPairs.hpp" #include "SigPolyBasis.hpp" #include "LogDomain.hpp" #include "MathicIO.hpp" #include MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS( SPairEarly, "Time early S-pair construction, elimination and ordering.", 0, 0, 1 ); MATHICGB_DEFINE_LOG_DOMAIN_WITH_DEFAULTS( SPairLate, "Time late S-pair elimination and ordering", 0, 0, 1 ); MATHICGB_DEFINE_LOG_DOMAIN( SPairLcm, "Displays the lcm of the S-pairs being considered in Buchberger's algorithm." ); MATHICGB_DEFINE_LOG_ALIAS("SPairs", "SPairEarly,SPairLate"); MATHICGB_DEFINE_LOG_ALIAS("SPairsDetail", "SPairs,SPairDegree,SPairLcm"); MATHICGB_NAMESPACE_BEGIN SPairs::SPairs(const PolyBasis& basis, bool preferSparseSPairs): mMonoid(basis.ring().monoid()), mOrderMonoid(OrderMonoid::create(mMonoid)), mBareMonoid(BareMonoid::create(mMonoid)), mQueue(QueueConfiguration(basis, mOrderMonoid, preferSparseSPairs)), mBasis(basis) {} std::pair SPairs::pop() { MATHICGB_LOG_TIME(SPairLate); // Must call addPairs for new elements before popping. MATHICGB_ASSERT(mEliminated.columnCount() == mBasis.size()); while (!mQueue.empty()) { const auto p = mQueue.topPair(); if (mBasis.retired(p.first) || mBasis.retired(p.second)) { mQueue.pop(); continue; } auto lcm = bareMonoid().alloc(); // todo: just keep one around instead bareMonoid().copy(orderMonoid(), *mQueue.topPairData(), *lcm); mQueue.pop(); MATHICGB_ASSERT(bareMonoid().isLcm( monoid(), mBasis.leadMono(p.first), monoid(), mBasis.leadMono(p.second), *lcm )); if (!advancedBuchbergerLcmCriterion(p.first, p.second, *lcm)) { mEliminated.setBit(p.first, p.second, true); return p; } } return std::make_pair(static_cast(-1), static_cast(-1)); } std::pair SPairs::pop(exponent& w) { MATHICGB_LOG_TIME(SPairLate); // Must call addPairs for new elements before popping. MATHICGB_ASSERT(mEliminated.columnCount() == mBasis.size()); for (; !mQueue.empty(); mQueue.pop()) { const auto p = mQueue.topPair(); if (mBasis.retired(p.first) || mBasis.retired(p.second)) continue; auto lcm = bareMonoid().alloc(); // todo: just keep one around instead bareMonoid().copy(orderMonoid(), *mQueue.topPairData(), *lcm); MATHICGB_ASSERT(bareMonoid().isLcm( monoid(), mBasis.leadMono(p.first), monoid(), mBasis.leadMono(p.second), *lcm )); if (advancedBuchbergerLcmCriterion(p.first, p.second, *lcm)) continue; if (w == 0) w = bareMonoid().degree(*lcm); else if (w != bareMonoid().degree(*lcm)) break; mQueue.pop(); mEliminated.setBit(p.first, p.second, true); MATHICGB_IF_STREAM_LOG(SPairLcm) { stream << "Scheduling S-pair with lcm "; MathicIO().writeMonomial (bareMonoid(), BareMonoid::HasComponent, *lcm, stream); stream << '.' << std::endl; }; return p; } return std::make_pair(static_cast(-1), static_cast(-1)); } namespace { // Records multiples of a basis element. // Used in addPairs(). class RecordIndexes : public MonoLookup::EntryOutput { public: RecordIndexes( size_t newGen, mathic::BitTriangle& eliminated, std::vector& indexes ): mNewGen(newGen), mEliminated(eliminated), mIndexes(indexes) {} virtual bool proceed(size_t index) { if (index == mNewGen) return true; mIndexes.push_back(index); // The S-pair (newGen, *it) corresponds to reducing the non-minimal // basis element *it. The S-polynomial corresponds to the first // step of that reduction. We tell the caller to reduce *it, so we // get to assume that this S-pair can be eliminated. This is important // because it sometimes allows us to eliminate an S-pair (newGen, x) // when (*it, x) has already been eliminated. We want to make use of // this opportunity before removing all the information about *it. mEliminated.setBit(mNewGen, index, true); return true; } private: size_t const mNewGen; mathic::BitTriangle& mEliminated; std::vector& mIndexes; }; } void SPairs::addPairsAssumeAutoReduce( size_t newGen, std::vector& toRetireAndReduce ) { { MATHICGB_LOG_TIME(SPairEarly); MATHICGB_ASSERT(mQueue.columnCount() == newGen); MATHICGB_ASSERT(newGen < mBasis.size()); MATHICGB_ASSERT(!mBasis.retired(newGen)); while (mEliminated.columnCount() < mBasis.size()) { if (mUseBuchbergerLcmHitCache) { MATHICGB_ASSERT(mEliminated.columnCount() == mBuchbergerLcmHitCache.size()); mBuchbergerLcmHitCache.push_back(0); } mEliminated.addColumn(); } RecordIndexes indexes(newGen, mEliminated, toRetireAndReduce); mBasis.monoLookup().multiples(mBasis.leadMono(newGen), indexes); } addPairs(newGen); } namespace { template class SecondIterator { public: typedef typename PairIterator::iterator_category iterator_category; typedef decltype(reinterpret_cast(0)->second) value_type; typedef typename PairIterator::difference_type difference_type; typedef value_type* pointer; typedef value_type& reference; SecondIterator(PairIterator pairIterator): mIterator(pairIterator) {} SecondIterator& operator++() {++mIterator; return *this;} const value_type operator*() const {return mIterator->second;} difference_type operator-(const SecondIterator& it) const { return mIterator - it.mIterator; } bool operator==(const SecondIterator& it) const { return mIterator == it.mIterator; } bool operator!=(const SecondIterator& it) const { return mIterator != it.mIterator; } private: PairIterator mIterator; }; template SecondIterator makeSecondIterator(Iter it) { return SecondIterator(it); } } void SPairs::addPairs(size_t newGen) { MATHICGB_LOG_TIME(SPairEarly); // Must call addPairs with newGen parameter in the sequence 0, 1, ... // newGen could be implicitly picked up from mQueue.columnCount(), but // doing it this way ensures that what happens is what the client thinks // is happening and offers an ASSERT to inform mistaken client code. MATHICGB_ASSERT(mQueue.columnCount() == newGen); MATHICGB_ASSERT(newGen < mBasis.size()); MATHICGB_ASSERT(!mBasis.retired(newGen)); while (mEliminated.columnCount() < mBasis.size()) { if (mUseBuchbergerLcmHitCache) { MATHICGB_ASSERT(mEliminated.columnCount() == mBuchbergerLcmHitCache.size()); mBuchbergerLcmHitCache.push_back(0); } mEliminated.addColumn(); } if (newGen == std::numeric_limits::max()) throw std::overflow_error ("Too large basis element index in constructing S-pairs."); OrderMonoid::MonoVector prePairMonos(orderMonoid()); typedef std::pair PrePair; std::vector prePairs; prePairMonos.reserve(newGen); prePairs.reserve(newGen); auto newLead = mBasis.leadMono(newGen); auto lcm = mBareMonoid.alloc(); for (size_t oldGen = 0; oldGen < newGen; ++oldGen) { if (mBasis.retired(oldGen)) continue; auto oldLead = mBasis.leadMono(oldGen); if (monoid().component(newLead) != monoid().component(oldLead)) { mEliminated.setBit(newGen, oldGen, true); continue; } if (monoid().relativelyPrime(newLead, oldLead)) { ++mStats.relativelyPrimeHits; mEliminated.setBit(newGen, oldGen, true); continue; } mBareMonoid.lcm(monoid(), newLead, monoid(), oldLead, *lcm); if (simpleBuchbergerLcmCriterion(newGen, oldGen, *lcm)) { mEliminated.setBit(newGen, oldGen, true); continue; } prePairMonos.push_back(bareMonoid(), *lcm); prePairs.emplace_back (prePairMonos.back().ptr(), static_cast(oldGen)); } std::sort(prePairs.begin(), prePairs.end(), [&](const PrePair& a, const PrePair& b) { return mQueue.configuration().compare (b.second, newGen, b.first, a.second, newGen, a.first); }); mQueue.addColumnDescending (makeSecondIterator(prePairs.begin()), makeSecondIterator(prePairs.end())); } size_t SPairs::getMemoryUse() const { return mQueue.getMemoryUse(); } bool SPairs::simpleBuchbergerLcmCriterion( size_t a, size_t b, BareMonoid::ConstMonoRef lcmAB ) const { MATHICGB_ASSERT( monoid().component(mBasis.leadMono(a)) == monoid().component(mBasis.leadMono(b)) ); MATHICGB_ASSERT(a < mBasis.size()); MATHICGB_ASSERT(b < mBasis.size()); MATHICGB_ASSERT(a != b); MATHICGB_ASSERT(!mBasis.retired(a)); MATHICGB_ASSERT(!mBasis.retired(b)); MATHICGB_ASSERT(bareMonoid().isLcm (monoid(), mBasis.leadMono(a), monoid(), mBasis.leadMono(b), lcmAB) ); MATHICGB_ASSERT(mEliminated.columnCount() == mBasis.size()); class Criterion : public MonoLookup::EntryOutput { public: Criterion( const size_t a, const size_t b, BareMonoid::ConstMonoRef lcmAB, const SPairs& sPairs ): mA(a), mB(b), mLcmAB(lcmAB), mSPairs(sPairs), mMonoid(sPairs.monoid()), mBareMonoid(sPairs.bareMonoid()), mBasis(sPairs.basis()), mHit(static_cast(-1)), mAlmostApplies(false) {} virtual bool proceed(size_t index) { MATHICGB_ASSERT(index < mBasis.size()); MATHICGB_ASSERT(!applies()); // should have stopped search in this case MATHICGB_ASSERT (mBareMonoid.divides(mMonoid, mBasis.leadMono(index), mLcmAB)); if (index == mA || index == mB) return true; mAlmostApplies = true; // check lcm(a,index) != lcm(a,b) <=> // exists i such that max(a[i], c[i]) != max(a[i],b[i]) <=> // exists i such that b[i] > a[i] && b[i] > c[i] <=> // exists i such that b[i] > max(a[i], c[i]) <=> // b does not divide lcm(a[i], c[i]) auto leadA = mBasis.leadMono(mA); auto leadB = mBasis.leadMono(mB); auto leadC = mBasis.leadMono(index); if ( !mSPairs.eliminated(index, mA) && mMonoid.dividesLcm(leadB, leadC, leadA) ) return true; // we had lcm(a,index) == lcm(a,b) // check lcm(b,index) != lcm(a,b) if ( !mSPairs.eliminated(index, mB) && mMonoid.dividesLcm(leadA, leadC, leadB) ) return true; // we had lcm(b,index) == lcm(a,b) mHit = index; return false; // stop search } BareMonoid::ConstMonoRef lcmAB() const {return mLcmAB;} bool almostApplies() const {return mAlmostApplies;} bool applies() const {return mHit != static_cast(-1);} size_t hit() const {return mHit;} private: const size_t mA; const size_t mB; BareMonoid::ConstMonoRef mLcmAB; const SPairs& mSPairs; const Monoid& mMonoid; const BareMonoid& mBareMonoid; const PolyBasis& mBasis; size_t mHit; // the divisor that made the criterion apply bool mAlmostApplies; // applies ignoring lcm(a,b)=lcm(a,c) complication }; bool applies = false; bool almostApplies = false; { Criterion criterion(a, b, lcmAB, *this); if (mUseBuchbergerLcmHitCache) { // Check cacheB first since when I tried this there was a higher hit rate // for cacheB than cacheA. Might not be a persistent phenomenon, but // there's no downside to trying out cacheB first so I'm going for that. // // I update the cache if the second check is a hit but not if the first // check is a hit. In the one test I did, the worst hit rate was from // updating the cache every time, the second best hit rate was from // not updating the cache (from cache hits) and the best hit rate was // from doing this. // // The idea is that when the first cache check is a hit, // the second cache member might have been a hit too, and updating it // might replace a high hit rate element with a low hit rate element, // which would be bad. When the second cache check is a hit, we know // that the first one wasn't (or we would have taken an early exit), // so we have reason to suspect that the first cache element is not // a high hit rate element. So it should be better to replace it. // That idea seems to be right since it worked better in the one // test I did. size_t cacheB = mBuchbergerLcmHitCache[b]; if ( !applies && !mBasis.retired(cacheB) && mBareMonoid.dividesWithComponent (monoid(), mBasis.leadMono(cacheB), criterion.lcmAB()) ) applies = !criterion.Criterion::proceed(cacheB); size_t cacheA = mBuchbergerLcmHitCache[a]; if ( !applies && !mBasis.retired(cacheA) && mBareMonoid.dividesWithComponent (monoid(), mBasis.leadMono(cacheA), criterion.lcmAB()) ) { applies = !criterion.Criterion::proceed(cacheA); if (applies) mBuchbergerLcmHitCache[b] = cacheA; } } if (applies) { if (mStats.late) ++mStats.buchbergerLcmCacheHitsLate; else ++mStats.buchbergerLcmCacheHits; } else { MATHICGB_ASSERT(!criterion.applies()); // This will be a tough nut to crack in terms of getting the types to match. mBasis.monoLookup().divisors (Monoid::toRef(BareMonoid::toOld(criterion.lcmAB())), criterion); applies = criterion.applies(); if (mUseBuchbergerLcmHitCache && applies) { MATHICGB_ASSERT(criterion.hit() < mBasis.size()); mBuchbergerLcmHitCache[a] = criterion.hit(); mBuchbergerLcmHitCache[b] = criterion.hit(); } } if (!applies) almostApplies = criterion.almostApplies(); } if (applies) { if (mStats.late) ++mStats.buchbergerLcmSimpleHitsLate; else ++mStats.buchbergerLcmSimpleHits; } MATHICGB_ASSERT(applies == simpleBuchbergerLcmCriterionSlow(a, b)); return applies; } bool SPairs::simpleBuchbergerLcmCriterionSlow(size_t a, size_t b) const { MATHICGB_ASSERT( monoid().component(mBasis.leadMono(a)) == monoid().component(mBasis.leadMono(b)) ); MATHICGB_ASSERT(a < mBasis.size()); MATHICGB_ASSERT(b < mBasis.size()); MATHICGB_ASSERT(a != b); MATHICGB_ASSERT(!mBasis.retired(a)); MATHICGB_ASSERT(!mBasis.retired(b)); MATHICGB_ASSERT(mEliminated.columnCount() == mBasis.size()); // todo: use iterators auto lcmAB = bareMonoid().alloc(); auto lcm = bareMonoid().alloc(); bareMonoid().lcm( monoid(), mBasis.leadMono(a), monoid(), mBasis.leadMono(b), *lcmAB ); size_t stop = mBasis.size(); size_t i = 0; for (; i < stop; ++i) { if (mBasis.retired(i)) continue; if (!bareMonoid().dividesWithComponent(monoid(), mBasis.leadMono(i), *lcmAB)) continue; if (i == a || i == b) continue; if (!eliminated(i, a)) { bareMonoid().lcm( monoid(), mBasis.leadMono(a), monoid(), mBasis.leadMono(i), *lcm ); if (bareMonoid().equal(*lcmAB, *lcm)) continue; } if (!eliminated(i, b)) { bareMonoid().lcm( monoid(), mBasis.leadMono(b), monoid(), mBasis.leadMono(i), *lcm ); if (bareMonoid().equal(*lcmAB, *lcm)) continue; } break; } return i != stop; } bool SPairs::advancedBuchbergerLcmCriterion( size_t a, size_t b, BareMonoid::ConstMonoRef lcmAB ) const { MATHICGB_ASSERT(a != b); MATHICGB_ASSERT(mEliminated.columnCount() == mBasis.size()); MATHICGB_ASSERT(bareMonoid().isLcm (monoid(), mBasis.leadMono(a), monoid(), mBasis.leadMono(b), lcmAB) ); mStats.late = true; if (simpleBuchbergerLcmCriterion(a, b, lcmAB)) { mStats.late = false; MATHICGB_ASSERT(advancedBuchbergerLcmCriterionSlow(a, b)); return true; } mStats.late = false; // *** Determine the graph vertices // graph contains pairs (index, state). index is the index of a basis // element that is a node in G. state indicates which of a and b that the // node in question is so far known to be connected to, if any. typedef std::vector > Graph; class GraphBuilder : public MonoLookup::EntryOutput { public: GraphBuilder(Graph& graph): mGraph(graph) {graph.clear();} virtual bool proceed(size_t index) { mGraph.push_back(std::make_pair(index, NotConnected)); return true; } private: Graph& mGraph; }; Graph& graph = mAdvancedBuchbergerLcmCriterionGraph; graph.clear(); GraphBuilder builder(graph); // This will be a tough nut to crack in terms of getting the types to match. mBasis.monoLookup().divisors (Monoid::toRef(BareMonoid::toOld(lcmAB)), builder); if (graph.size() <= 3) { // For the graph approach to be better than the simpler approach of // considering triples, there has to be more than 3 nodes in the graph. MATHICGB_ASSERT(!advancedBuchbergerLcmCriterionSlow(a, b)); return false; } // *** Set up todo with a and b // todo points to elements (nodes) of graph to process. std::vector todo; Graph::iterator const graphEnd = graph.end(); for (Graph::iterator it = graph.begin(); it != graphEnd; ++it) { if (it->first == a) it->second = ConnectedA; else if (it->first == b) it->second = ConnectedB; else continue; todo.push_back(it); } // *** Follow edges in the graph // We stop as soon as we find a node that is connected to both a and b, // since then a and b are connected so that the criterion applies. bool applies = false; while (!applies && !todo.empty()) { size_t const currentIndex = todo.back()->first; Connection const currentConnect = todo.back()->second; MATHICGB_ASSERT(currentConnect != NotConnected); todo.pop_back(); // loop through all potential edges (currentIndex, otherIndex) auto currentLead = mBasis.leadMono(currentIndex); for (Graph::iterator other = graph.begin(); other != graphEnd; ++other) { Connection const otherConnect = other->second; if (currentConnect == otherConnect) continue; size_t const otherIndex = other->first; MATHICGB_ASSERT(otherIndex != currentIndex); auto const otherLead = mBasis.leadMono(otherIndex); // Note that // lcm(c,d) != lcmAB <=> // exists i such that max(c[i], d[i]) < lcmAB[i] <=> // exists i such that lcmAB[i] > c[i] && lcmAB[i] > d[i] <=> // exists i such that lcmAB[i] > max(c[i], d[i]) <=> // lcmAB does not divide lcm(c[i], d[i]) if ( !eliminated(currentIndex, otherIndex) && monoid().dividesLcm (bareMonoid(), lcmAB, monoid(), currentLead, otherLead) ) continue; // not an edge in G if (otherConnect == NotConnected) { other->second = currentConnect; todo.push_back(other); } else { // At this point we have found an edge between a node connected to // a and a node connected to b. So a and b are connected. MATHICGB_ASSERT(currentConnect != otherConnect); applies = true; break; } } } if (applies) ++mStats.buchbergerLcmAdvancedHits; // if (graph.size() >= 10) // std::cout << "[adv size=" << graph.size() << " result= " << applies << std::endl; MATHICGB_ASSERT(applies == advancedBuchbergerLcmCriterionSlow(a, b)); return applies; } bool SPairs::advancedBuchbergerLcmCriterionSlow(size_t a, size_t b) const { MATHICGB_ASSERT(a != b); MATHICGB_ASSERT(mEliminated.columnCount() == mBasis.size()); auto lcmAB = monoid().alloc(); auto lcm = monoid().alloc(); monoid().lcm(mBasis.leadMono(a), mBasis.leadMono(b), lcmAB); size_t stop = mBasis.size(); // *** Build the graph vertices // graph contains pairs (index, state). index is the index of a basis // that is a node in G. state indicates which of a and b that the node // in question is so far known to be connected to. std::vector > graph; std::vector todo; // indexes into graph to process. for (size_t i = 0; i != stop; ++i) { if (mBasis.retired(i)) continue; if (!monoid().dividesWithComponent(mBasis.leadMono(i), *lcmAB)) continue; Connection con = NotConnected; if (i == a) { con = ConnectedA; todo.push_back(graph.size()); } else if (i == b) { con = ConnectedB; todo.push_back(graph.size()); } graph.push_back(std::make_pair(i, con)); } // *** Follow edges in the graph // We stop as soon as we find a node that is connected to both a and b, // since then a and b are connected so that the criterion applies. bool applies = false; while (!applies && !todo.empty()) { MATHICGB_ASSERT(todo.size() <= graph.size()); std::pair const node = graph[todo.back()]; todo.pop_back(); MATHICGB_ASSERT(node.second != NotConnected); // loop through all potential edges (node.first, i) ConstMonoRef leadNode = mBasis.leadMono(node.first); for (size_t i = 0; i < graph.size(); ++i) { if (node.second == graph[i].second) continue; MATHICGB_ASSERT(graph[i].first != node.first); const size_t other = graph[i].first; auto const leadOther = mBasis.leadMono(other); monoid().lcm(leadNode, leadOther, lcm); if (!eliminated(node.first, other) && monoid().equal(*lcm, *lcmAB)) continue; // not an edge in G if (graph[i].second == NotConnected) { graph[i].second = node.second; todo.push_back(i); } else { // At this point we have found an edge between something a node to // a and a node connected to b. So a and b are connected. MATHICGB_ASSERT(graph[i].second != node.second); applies = true; break; } } } MATHICGB_ASSERT(applies || !simpleBuchbergerLcmCriterionSlow(a, b)); return applies; } SPairs::Stats SPairs::stats() const { size_t const columnCount = mQueue.columnCount(); mStats.sPairsConsidered = columnCount * (columnCount - 1) / 2; return mStats; } std::string SPairs::name() const { return mQueue.name(); } void SPairs::QueueConfiguration::computePairData( size_t a, size_t b, OrderMonoid::MonoRef orderBy ) const { MATHICGB_ASSERT(a != b); MATHICGB_ASSERT(a < mBasis.size()); MATHICGB_ASSERT(b < mBasis.size()); if (mBasis.retired(a) || mBasis.retired(b)) { // todo: do something special here? return; //return false; } Monoid::ConstMonoRef leadA = mBasis.leadMono(a); Monoid::ConstMonoRef leadB = mBasis.leadMono(b); orderMonoid().lcm(monoid(), leadA, monoid(), leadB, orderBy); return; //todo: return true; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/SPairs.hpp000077500000000000000000000252451311555162500204230ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_S_PAIRS_GUARD #define MATHICGB_S_PAIRS_GUARD #include "PolyBasis.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN class PolyBasis; // Stores the set of pending S-pairs for use in the classic Buchberger // algorithm. Also eliminates useless S-pairs and orders the S-pairs. class SPairs { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Exponent Exponent; typedef Monoid::Mono Mono; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; /// This monoid is used for computations to determine whether to eliminate /// an S-pair. These computations do not require anything beyond just /// considering the exponents. Since recomputing characteristics of /// lcms such as hash and degree is expensive (unlike for a product), it is /// worthwhile to disable those characteristics that we do not need. typedef MonoMonoid BareMonoid; /// This monoid is used to order S-pairs by their lcm. Here we need to /// to store the ordering data for fast comparison, but we do not need /// hashes. typedef MonoMonoid OrderMonoid; SPairs(const PolyBasis& basis, bool preferSparseSPairs); // Returns the number of S-pairs in the data structure. size_t pairCount() const {return mQueue.pairCount();} // Returns true if no pending S-pairs remain. bool empty() const {return mQueue.empty();} // Removes the minimal S-pair from the data structure and returns it. // The S-polynomial of that pair is assumed to reduce to zero, either // because it already does, or because it did not reduce to zero and then // that caused the addition of another basis element. If this assumption // is broken, S-pair elimination may give incorrect results. // // Returns the pair (invalid,invalid) if there are no S-pairs left to // return, where invalid is static_cast(-1). This can happen even // if empty() returned false prior to calling pop(), since the S-pairs in // the queue may have been found to be useless. std::pair pop(); // As pop(), but only pops S-pairs whose lcm have the passed-in // weight. If deg is already 0, then instead set deg to the weight // of the returned S-pair, if any. std::pair pop(exponent& w); // Add the pairs (index,a) to the data structure for those a such that // a < index. Some of those pairs may be eliminated if they can be proven // to be useless. index must be a valid index of a basis element // and must only be called once per basis element and must be 1 more // than the value of index for the previous call to addPairs, starting // at zero for the first call. void addPairs(size_t index); // As addPairs, but assuming auto-reduction of the basis will happen. // This method assumes that if lead(index) divides lead(x) for a basis // element x, then x will be retired from the basis and reduced. toReduce // will contain those indices x. void addPairsAssumeAutoReduce(size_t index, std::vector& toRetireAndReduce); // Returns true if the S-pair (a,b) is known to be useless. Even if the // S-pair is not useless now, it will become so later. At the latest, an // S-pair becomes useless when its S-polynomial has been reduced to zero. bool eliminated(size_t a, size_t b) const { return mEliminated.bitUnordered(a, b); } const Monoid& monoid() const {return mMonoid;} const PolyBasis& basis() const {return mBasis;} size_t getMemoryUse() const; struct Stats { Stats(): sPairsConsidered(0), relativelyPrimeHits(0), buchbergerLcmSimpleHits(0), buchbergerLcmAdvancedHits(0), buchbergerLcmCacheHits(0), late(false), buchbergerLcmSimpleHitsLate(0), buchbergerLcmCacheHitsLate(0) {} unsigned long long sPairsConsidered; unsigned long long relativelyPrimeHits; unsigned long long buchbergerLcmSimpleHits; unsigned long long buchbergerLcmAdvancedHits; unsigned long long buchbergerLcmCacheHits; bool late; // if set to true then simpleBuchbergerLcmCriterion sets the following 2 instead: unsigned long long buchbergerLcmSimpleHitsLate; unsigned long long buchbergerLcmCacheHitsLate; }; Stats stats() const; std::string name() const; private: const BareMonoid& bareMonoid() const {return mBareMonoid;} const OrderMonoid& orderMonoid() const {return mOrderMonoid;} // Returns true if Buchberger's second criterion for eliminating useless // S-pairs applies to the pair (a,b). Define // l(a,b) = lcm(lead(a), lead(b)). // The criterion says that if there is some other basis element c such that // lead(c)|l(a,b) // and // l(a,c) has a representation and // l(b,c) has a representation // then (a,b) has a representation too, so we do not need to reduce it. // // This criterion is easy to get wrong in cases where // l(a,b) = l(a,c) = l(b,c) // since then there is the potential to erroneously eliminate all the three // pairs among a,b,c on the assumption that the other two pairs will reduce // to zero. In fact only one of the pairs should be eliminated. We leave such // cases to the advanced criterion, except if an S-pair has already been // eliminated - in that case we do not check to see if the lcm's are the same // as it is not necessary to do so. bool simpleBuchbergerLcmCriterion( size_t a, size_t b, BareMonoid::ConstMonoRef lcmAB ) const; // As the non-slow version, but uses simpler and slower code. bool simpleBuchbergerLcmCriterionSlow(size_t a, size_t b) const; // Improves on Buchberger's second criterion by using connection in a graph // to determine if an S-pair can be eliminated. This can eliminate some pairs // that cannot be eliminated by looking at any one triple of generators. // // The algorithm is based on considering an undirected graph G. // Each vertex of G represents a basis element whose lead monomial divides // lcmAB. There is an edge (c,d) if lcm(c,d) != lcm(a,b) or if (c,d) has // been eliminated. It is a theorem that if there is a path from a to b // in G then (a,b) is a useless S-pair that can be eliminated. bool advancedBuchbergerLcmCriterion (size_t a, size_t b, BareMonoid::ConstMonoRef lcmAB) const; // As the non-slow version, but uses simpler and slower code. bool advancedBuchbergerLcmCriterionSlow(size_t a, size_t b) const; const Monoid& mMonoid; OrderMonoid mOrderMonoid; BareMonoid mBareMonoid; class QueueConfiguration { public: QueueConfiguration( const PolyBasis& basis, const OrderMonoid& orderMonoid, const bool preferSparseSPairs ): mBasis(basis), mMonoid(basis.ring().monoid()), mOrderMonoid(orderMonoid), mPreferSparseSPairs(preferSparseSPairs) {} typedef OrderMonoid::Mono PairData; void computePairData (size_t col, size_t row, OrderMonoid::MonoRef m) const; typedef bool CompareResult; bool compare( size_t colA, size_t rowA, OrderMonoid::ConstMonoPtr a, size_t colB, size_t rowB, OrderMonoid::ConstMonoPtr b ) const { const auto cmp = orderMonoid().compare(*a, *b); if (cmp == GT) return true; if (cmp == LT) return false; const bool aRetired = mBasis.retired(rowA) || mBasis.retired(colA); const bool bRetired = mBasis.retired(rowB) || mBasis.retired(colB); if (aRetired || bRetired) return !bRetired; if (mPreferSparseSPairs) { const auto termCountA = mBasis.basisElement(colA).termCount() + mBasis.basisElement(rowA).termCount(); const auto termCountB = mBasis.basisElement(colB).termCount() + mBasis.basisElement(rowB).termCount(); if (termCountA > termCountB) return true; if (termCountA < termCountB) return false; } return colA + rowA > colB + rowB; } bool cmpLessThan(bool v) const {return v;} // The following methods are not required of a configuration. OrderMonoid::Mono allocPairData() {return orderMonoid().alloc();} void freePairData(OrderMonoid::Mono&& mono) { return orderMonoid().free(std::move(mono)); } private: const Monoid& monoid() const {return mMonoid;} const OrderMonoid& orderMonoid() const {return mOrderMonoid;} const PolyBasis& mBasis; const Monoid& mMonoid; const OrderMonoid& mOrderMonoid; const bool mPreferSparseSPairs; }; typedef mathic::PairQueue Queue; Queue mQueue; // The bit at (i,j) is set to true if it is known that the S-pair between // basis element i and j does not have to be reduced. This can be due to a // useless S-pair criterion eliminating that pair, or it can be because the // S-polynomial of that pair has already been reduced. mathic::BitTriangle mEliminated; const PolyBasis& mBasis; mutable Stats mStats; static const bool mUseBuchbergerLcmHitCache = true; mutable std::vector mBuchbergerLcmHitCache; enum Connection { // used in advancedBuchbergerLcmCriterion(). NotConnected, // not known to be connected to a or b ConnectedA, // connected to a ConnectedB // connected to b }; // Variable used only inside advancedBuchbergerLcmCriterion(). mutable std::vector > mAdvancedBuchbergerLcmCriterionGraph; friend void mathic::PairQueueNamespace::constructPairData (void*, mathic::PairQueueNamespace::Index, mathic::PairQueueNamespace::Index, QueueConfiguration&); friend void mathic::PairQueueNamespace::destructPairData (OrderMonoid::Mono*, mathic::PairQueueNamespace::Index, mathic::PairQueueNamespace::Index, QueueConfiguration&); }; MATHICGB_NAMESPACE_END namespace mathic { namespace PairQueueNamespace { template<> inline void constructPairData( void* memory, const Index col, const Index row, mgb::SPairs::QueueConfiguration& conf ) { MATHICGB_ASSERT(memory != 0); MATHICGB_ASSERT(col > row); auto pd = new (memory) mgb::SPairs::OrderMonoid::Mono(conf.allocPairData()); conf.computePairData(col, row, *pd); } template<> inline void destructPairData( mgb::SPairs::OrderMonoid::Mono* pd, const Index col, const Index row, mgb::SPairs::QueueConfiguration& conf ) { MATHICGB_ASSERT(pd != 0); MATHICGB_ASSERT(col > row); conf.freePairData(std::move(*pd)); } } } #endif mathicgb-master/src/mathicgb/Scanner.cpp000077500000000000000000000111251311555162500205760ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "Scanner.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN static const size_t BufferSize = #ifdef MATHICGB_DEBUG 1; #else 10 * 1024; #endif void reportSyntaxError(std::string s, uint64 lineNumber) { std::ostringstream out; out << "Syntax error on line " << lineNumber << ": " << s; mathic::reportError(out.str()); } void Scanner::reportError(std::string msg) const { reportSyntaxError(msg, lineCount()); } Scanner::Scanner(FILE* input): mFile(input), mStream(0), mLineCount(1), mChar(' '), mBuffer(BufferSize), mBufferPos(mBuffer.end()) { get(); } Scanner::Scanner(std::istream& input): mFile(0), mStream(&input), mLineCount(1), mChar(' '), mBuffer(BufferSize), mBufferPos(mBuffer.end()) { get(); } Scanner::Scanner(const char* const input): mFile(0), mStream(0), mLineCount(1), mChar(' '), mBuffer(input, input + std::strlen(input)), mBufferPos(mBuffer.begin()) { get(); } Scanner::Scanner(const std::string& input): mFile(0), mStream(0), mLineCount(1), mChar(' '), mBuffer(input.begin(), input.end()), mBufferPos(mBuffer.begin()) { get(); } bool Scanner::match(const char* const str) { eatWhite(); MATHICGB_ASSERT(str != 0); const auto size = std::strlen(str); if (!ensureBuffer(size)) return false; if (size == 0) return true; if (peek() != *str) return false; if (std::strncmp(&*mBufferPos, str + 1, size - 1) != 0) return false; ignore(size); return true; } bool Scanner::ensureBuffer(size_t min) { const auto got = size_t(std::distance(mBufferPos, mBuffer.end()) + 1); return got >= min || readBuffer(min - got); } void Scanner::expect(const char* str) { MATHICGB_ASSERT(str != 0); eatWhite(); const char* it = str; while (*it != '\0') { int character = get(); if (*it == character) { ++it; continue; } // Read the rest of what is there to improve error message. // TODO: read at least one char in total even if not alnum. std::ostringstream got; if (character == EOF && it == str) got << "no more input"; else { got << '\"' << std::string(str, it); if (isalnum(character)) got << static_cast(character); while (isalnum(peek())) got << static_cast(get()); got << '\"'; } reportErrorUnexpectedToken(str, got.str()); } } void Scanner::expectEOF() { eatWhite(); if (get() != EOF) reportErrorUnexpectedToken("no more input", ""); } void Scanner::errorExpectTwo(char a, char b, int got) { MATHICGB_ASSERT(a != got && b != got); std::ostringstream err; err << '\'' << a << "' or '" << b << '\''; reportErrorUnexpectedToken(err.str(), got); } void Scanner::errorExpectOne(char expected, int got) { MATHICGB_ASSERT(expected != got); std::ostringstream err; err << '\'' << expected << '\''; reportErrorUnexpectedToken(err.str(), got); } void Scanner::reportErrorUnexpectedToken(const std::string& expected, int got) { std::ostringstream gotDescription; if (got == EOF) gotDescription << "no more input"; else gotDescription << '\'' << static_cast(got) << '\''; reportErrorUnexpectedToken(expected, gotDescription.str()); } void Scanner::reportErrorUnexpectedToken( const std::string& expected, const std::string& got ) { std::ostringstream errorMsg; errorMsg << "Expected " << expected; if (got != "") errorMsg << ", but got " << got; errorMsg << '.'; reportError(errorMsg.str()); } bool Scanner::readBuffer(size_t minRead) { auto saveCount = std::distance(mBufferPos, mBuffer.end()); if (mBufferPos != mBuffer.begin() && mBufferPos != mBuffer.end()) std::copy(mBufferPos, mBuffer.end(), mBuffer.begin()); mBuffer.resize(std::max(saveCount + minRead, mBuffer.capacity())); auto readInto = reinterpret_cast(mBuffer.data() + saveCount); auto readCount = mBuffer.size() - saveCount; size_t didReadCount = 0; if (mFile != 0) { didReadCount = fread(readInto, 1, readCount, mFile); } else if (mStream != 0) { mStream->read(readInto, readCount); const std::streamsize maxSizeT = std::numeric_limits::type>::max(); if (mStream->gcount() > maxSizeT) throw std::bad_alloc(); didReadCount = static_cast(mStream->gcount()); } mBuffer.resize(saveCount + didReadCount); mBufferPos = mBuffer.begin(); return didReadCount >= minRead; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/Scanner.hpp000077500000000000000000000174671311555162500206220ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SCANNER_GUARD #define MATHICGB_SCANNER_GUARD #include "PrimeField.hpp" #include "Unchar.hpp" #include #include #include #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// This class offers an input interface which is more convenient and /// often more efficient than dealing with a FILE* or std::istream /// directly. It keeps track of the current line number to report /// better error messages. Only one Scanner should be reading from a /// given FILE* or std::istream due to buffering and line number counting. /// /// All input methods whose documentation does not specifically say /// otherwise skip whitespace. /// /// There are four concepts for consuming input through a Scanner: /// /// Read X: Require an X to be in the input, and return what is read. /// /// Expect X: Require the exact value X to be in the input and skip past it. /// /// Match X: Return true if the exact value X is in the input, and in that case /// skip past it. Otherwise return false and do nothing else. /// /// MatchRead X: Return true of an X is in the input. In that case, /// read the X into a reference parameter and return true. /// /// Peek X: Return true if X is the next thing int he input. Do not skip /// past anything. May or may not skip whitespace depending on what X is. /// /// If a requirement is not met, Scanner reports a syntax error. class Scanner { public: /// Construct a Scanner object reading from the input FILE*. Scanner(FILE* input); /// Construct a Scanner object reading from the input std::istream. Scanner(std::istream& input); /// Construct a Scanner object reading from the input string. Scanner(const char* const input); /// Construct a Scanner object reading from the input string. Scanner(const std::string& input); /// Reads a single character from the stream. int get(); /// Takes count characters off the stream. void ignore(size_t count); /// Return true if the next character is c, and in that case skip /// past it. bool match(char c); /// Return true if no more input. bool matchEOF(); bool match(const char* const str); /// Require the next character to be equal to expected. This /// character is skipped past. void expect(char expected); /// Require the next character to be equal to a or b. This character /// is skipped past. void expect(char a, char b); /// Require the following characters to be equal to str. These /// characters are skipped past. void expect(const char* str); /// Require the following characters to be equal to str. These /// characters are skipped past. void expect(const std::string& str) {expect(str.c_str());} /// Require that there is no more input. void expectEOF(); /// Reads a T. T must be an integer type with a std::numeric_limits /// specialization. Negative numbers are allows if T is signed. template T readInteger(bool negate = false); template typename PrimeField::Element readModular( const PrimeField& field, const bool negate = false ); /// Reads a T if it is there. Does not recognize + or - as the start /// of an integer. template bool matchReadIntegerNoSign(T& t, bool negate = false); /// Returns the next character or EOF. Does not skip whitespace. int peek() {return mChar;} /// Returns true if the next character is a digit. Does not skip /// whitespace. bool peekDigit() {return std::isdigit(peek());} bool peekAlpha() {return std::isalpha(peek());} /// Returns true if the next character is whitespace. Does not skip /// whitespace. Whitespace is defined by std::isspace(). bool peekWhite() {return isspace(peek());} /// Returns true if the next character is + or -. Does not skip /// whitespace. bool peekSign() {return peek() == '+' || peek() == '-';} /// Returns the number of newlines seen plus one. Does not skip /// whitespace. uint64 lineCount() const {return mLineCount;} /// Reads past any whitespace. inline void eatWhite(); void reportError(std::string msg) const; private: void errorExpectTwo(char a, char b, int got); void errorExpectOne(char expected, int got); void reportErrorUnexpectedToken(const std::string& expected, int got); void reportErrorUnexpectedToken (const std::string& expected, const std::string& got); bool ensureBuffer(size_t min); bool readBuffer(size_t minRead); FILE* mFile; std::istream* mStream; uint64 mLineCount; int mChar; // next character on stream std::vector mBuffer; std::vector::iterator mBufferPos; }; inline bool Scanner::matchEOF() { eatWhite(); return peek() == EOF; } inline bool Scanner::match(char c) { eatWhite(); if (c == peek()) { get(); return true; } else return false; } inline void Scanner::expect(char a, char b) { eatWhite(); int got = get(); if (got != a && got != b) errorExpectTwo(a, b, got); } inline void Scanner::expect(char expected) { eatWhite(); int got = get(); if (got != expected) errorExpectOne(expected, got); } inline void Scanner::eatWhite() { while (peekWhite()) get(); } inline int Scanner::get() { if (mChar == '\n') ++mLineCount; int oldChar = mChar; if (mBufferPos == mBuffer.end() && !readBuffer(1)) mChar = EOF; else { mChar = *mBufferPos; ++mBufferPos; } return oldChar; } inline void Scanner::ignore(size_t count) { for (size_t i = 0; i < count; ++i) get(); } template T Scanner::readInteger(const bool negate) { static_assert(std::numeric_limits::is_integer, ""); eatWhite(); const bool minus = !match('+') && match('-'); const bool positive = minus == negate; if (!peekDigit()) reportErrorUnexpectedToken("an integer", ""); // Skip leading zeroes and return if the number is zero. if (peek() == '0') { while (peek() == '0') get(); if (!peekDigit()) return static_cast(0); } MATHICGB_ASSERT(peekDigit()); MATHICGB_ASSERT(peek() != 0); // Checking this here allows us to recognize -0 as non-negative. if (!positive && !std::numeric_limits::is_signed) reportErrorUnexpectedToken("a positive integer", ""); const auto min = std::numeric_limits::min(); const auto max = std::numeric_limits::max(); auto t = static_cast(0); while (peekDigit()) { const auto c = static_cast(get()); const auto d = positive ? c - '0' : -(c - '0'); if (positive ? t > (max - d) / 10 : t < (min - d) / 10) { std::ostringstream err; err << "an integer in the range [" << unchar(min) << ", " << unchar(max) << ']'; reportErrorUnexpectedToken(err.str(), ""); } t = t * 10 + d; } MATHICGB_ASSERT(t != static_cast(0)); // We already handled zero above. return t; } template typename PrimeField::Element Scanner::readModular( const PrimeField& field, const bool negate ) { static_assert(std::numeric_limits::is_integer, ""); // Otherwise we need to consider that the most negative value's // negative cannot be represented as a positive number when reading. // todo: reinstate this assert once we get rid of signed coefficients. //static_assert(!std::is_signed::value, ""); eatWhite(); const bool minus = !match('+') && match('-'); const bool positive = minus == negate; if (!peekDigit()) reportErrorUnexpectedToken("an integer", ""); const auto e = field.toElement(readInteger(false)); return positive ? e : field.negative(e); } template bool Scanner::matchReadIntegerNoSign(T& t, bool negate) { if (peekDigit()) { t = readInteger(negate); return true; } else return false; } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/ScopeExit.hpp000077500000000000000000000057611311555162500211260ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SCOPE_EXIT_GUARD #define MATHICGB_SCOPE_EXIT_GUARD MATHICGB_NAMESPACE_BEGIN // Guard holds an action to call and calls it unless it has been released. template class Guard { public: ~Guard() { if (mOwning && mActive) mAction(); } private: friend struct GuardMaker; Guard(T&& action, const bool& active): mAction(std::move(action)), mOwning(true), mActive(active) {} // Most compilers should elide the call to this construtor, but it must be // here anyway and we should support even a crazy compiler that decides to // call it. Guard(Guard&& guard): mAction(std::move(guard.mAction)), mOwning(true), mActive(guard.mActive) { assert(guard.mActive); guard.mOwning = false; // to avoid calling mAction twice } bool mOwning; const bool& mActive; const T mAction; }; // The class user code interacts with to dismiss an action. class Dismisser { public: Dismisser(bool& active): mActive(active) {} void dismiss() {mActive = false;} private: bool& mActive; }; // Helper class that allows convenient syntax for the macro by overloading // operator+. struct GuardMaker { public: GuardMaker(const bool& active): mActive(active) {} template Guard operator+(T&& t) {return Guard(std::forward(t), mActive);} private: const bool& mActive; }; MATHICGB_NAMESPACE_END // Example, with no need to dismiss: // FILE* file = fopen("file.txt", "r"); // MATHICGB_SCOPE_EXIT() { // fclose(file); // std::cout << "file closed"; // }; // // ... // return; // the file is closed // // Example, with need to dismiss: // v.push_back(5); // MATHICGB_SCOPE_EXIT(name) {v.pop_back();}; // // ... // if (error) // return; // the pop_back is done // name.dismiss(); // return; // the pop_back is not done // // The middle line is a no-op if the name parameter expands to nothing. // When NAME expands to nothing, we need the static_cast to prevent // the compiler from parsing the middle line as a redeclaration of // myBool. In the final line we use that a const reference keeps // temporary objects alive until the end of the scope. It would be correct // to copy, but this way we can keep the copy constructor private // and help out any compiler that has issue with eliding that copy. #define MATHICGB_SCOPE_EXIT(NAME) \ bool MATHICGB_UNIQUE(active) = true; \ ::mgb::Dismisser NAME(static_cast(MATHICGB_UNIQUE(active))); \ const auto& MATHICGB_UNIQUE(guard) = \ ::mgb::GuardMaker(MATHICGB_UNIQUE(active)) + [&] // Without this pragma, MSVC will say // warning C4003: not enough actual parameters for macro 'MYLIB_SCOPE_EXIT' // when using MYLIB_SCOPE_EXIT without a name parameter. Not very happy about // turning off the warning. I wonder if there is a way to avoid the warning in // this case without turning it off. #pragma warning (disable: 4003) #endif mathicgb-master/src/mathicgb/SigPolyBasis.cpp000077500000000000000000000367111311555162500215650ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "SigPolyBasis.hpp" #include "Poly.hpp" #include "MathicIO.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN SigPolyBasis::SigPolyBasis( const PolyRing& R0, int monoLookupType, int monTableType, bool preferSparseReducers ): mMonoLookupFactory (MonoLookup::makeFactory(R0.monoid(), monoLookupType)), mRatioSorted(RatioOrder(mSigLeadRatio, R0.monoid())), mMinimalMonoLookup(mMonoLookupFactory->make(preferSparseReducers, true)), mBasis(R0, mMonoLookupFactory->make(preferSparseReducers, true)), mPreferSparseReducers(preferSparseReducers) { mTmp = mBasis.ring().allocMonomial(); const_cast(mBasis.monoLookup()).setSigBasis(*this); mMinimalMonoLookup->setSigBasis(*this); } SigPolyBasis::~SigPolyBasis() { MATHICGB_ASSERT(mBasis.size() == mSignatures.size()); MATHICGB_ASSERT(mBasis.size() == mSigLeadRatio.size()); for (size_t i = 0; i < mBasis.size(); i++) { if (!mSignatures[i].isNull()) monoid().freeRaw(*mSignatures[i]); if (!mSigLeadRatio[i].isNull()) monoid().freeRaw(*mSigLeadRatio[i]); } for (size_t i = 0; i < mSignatureLookup.size(); ++i) delete mSignatureLookup[i]; mBasis.ring().freeMonomial(mTmp); } void SigPolyBasis::addComponent() { std::unique_ptr lookup = mMonoLookupFactory->make(mPreferSparseReducers, true); lookup->setSigBasis(*this); mSignatureLookup.push_back(0); mSignatureLookup.back() = lookup.release(); // only release after alloc } void SigPolyBasis::insert(Mono ownedSig, std::unique_ptr f) { MATHICGB_ASSERT(f.get() != nullptr); MATHICGB_ASSERT(!f->isZero()); MATHICGB_ASSERT(!field().isZero(f->leadCoef())); MATHICGB_ASSERT(!ownedSig.isNull()); MATHICGB_ASSERT(monoid().fromPool(*ownedSig)); const auto index = mSignatures.size(); mSignatures.push_back(ownedSig.release()); auto sig = *mSignatures.back(); const auto component = monoid().component(sig); MATHICGB_ASSERT(component < mSignatureLookup.size()); mSignatureLookup[component]->insert(sig, index); auto ratio = ring().allocMonomial(); monoid().divideToNegative(f->leadMono(), sig, ratio); mSigLeadRatio.push_back(ratio); const auto lead = f->leadMono(); mBasis.insert(std::move(f)); if (mBasis.leadMinimal(mBasis.size() - 1)) { mMinimalMonoLookup->removeMultiples(lead); mMinimalMonoLookup->insert(lead, index); } MATHICGB_ASSERT(mMinimalMonoLookup->type() == 0 || mBasis.minimalLeadCount() == mMinimalMonoLookup->size()); MATHICGB_ASSERT(mSignatures.size() == index + 1); MATHICGB_ASSERT(mBasis.size() == index + 1); if (!mUseRatioRank) return; // compute rank of the ratio auto pos = mRatioSorted.insert(index); again: Rank prevRank; if (pos == mRatioSorted.begin()) prevRank = 0; else { auto prev = pos; --prev; prevRank = mRatioRanks[*prev]; if (monoid().equal(ratio, *mSigLeadRatio[*prev])) { mRatioRanks.push_back(prevRank); return; } } Rank nextRank; auto next = pos; ++next; if (next == mRatioSorted.end()) nextRank = std::numeric_limits::max(); else { nextRank = mRatioRanks[*next]; if (monoid().equal(ratio, *mSigLeadRatio[*next])) { mRatioRanks.push_back(nextRank); return; } } MATHICGB_ASSERT(prevRank < nextRank); // this formula avoids the overflow inherent in prevRank + nextRank; Rank rank = prevRank + (nextRank - prevRank) / 2; // must have at least 1 space between ranks to support // queries for non-basis element rank if (rank == 0 || // must leave space for smaller ratio rank == std::numeric_limits::max() || // shouldn't happen nextRank - prevRank < 4) { // 4 as require: prev, gap, new, gap, next // size plus 1 to account for the gaps at the beginning and end. size_t increment = std::numeric_limits::max() / (mSignatures.size() + 1); if (increment == 0) increment = 2; MATHICGB_ASSERT(!mRatioSorted.empty()); size_t rankSum = increment; // leave a gap at beginning Rank prevRank = *mRatioRanks.begin(); auto end = mRatioSorted.end(); for (auto it = mRatioSorted.begin(); it != end; ++it) { if (it == pos) continue; if (mRatioRanks[*it] != prevRank) rankSum += increment; prevRank = mRatioRanks[*it]; mRatioRanks[*it] = rankSum; } goto again; } MATHICGB_ASSERT(rank > 0); MATHICGB_ASSERT(rank < std::numeric_limits::max()); MATHICGB_ASSERT(prevRank + 1 < rank && rank < nextRank - 1); mRatioRanks.push_back(rank); MATHICGB_ASSERT(mRatioRanks.size() == index + 1); #ifdef MATHICGB_DEBUG // Check that at least one space has been left between every rank MATHICGB_ASSERT(mRatioRanks[*mRatioSorted.begin()] > 0); MATHICGB_ASSERT(mRatioRanks[*mRatioSorted.rbegin()] < std::numeric_limits::max()); auto it2 = mRatioSorted.begin(); for (++it2; it2 != mRatioSorted.end(); ++it2) { auto prev = it2; --prev; MATHICGB_ASSERT(mRatioRanks[*it2] == mRatioRanks[*prev] || mRatioRanks[*it2] - 1 > mRatioRanks[*prev]); } #endif } size_t SigPolyBasis::regularReducer( ConstMonoRef sig, ConstMonoRef term ) const { size_t reducer = monoLookup().regularReducer(sig, term); #ifdef MATHICGB_SLOW_DEBUG const size_t debugValue = regularReducerSlow(sig, term); if (reducer == static_cast(-1)) { MATHICGB_SLOW_ASSERT(debugValue == static_cast(-1)); } else { MATHICGB_SLOW_ASSERT(debugValue != static_cast(-1)); monomial m = ring().allocMonomial(); MATHICGB_SLOW_ASSERT (ring().monomialIsDivisibleBy(term, leadMono(reducer))); ring().monomialDivide(term, leadMono(reducer), m); ring().monomialMultTo(m, signature(reducer)); MATHICGB_SLOW_ASSERT(monoid().lessThan(m, sig)); ring().freeMonomial(m); } #endif return reducer; } size_t SigPolyBasis::regularReducerSlow( ConstMonoRef sig, ConstMonoRef term ) const { monomial m = ring().allocMonomial(); const size_t stop = size(); for (size_t be = 0; be < stop; ++be) { if (!monoid().divides(leadMono(be), term)) continue; monoid().divide(leadMono(be), term, m); monoid().multiplyInPlace(signature(be), m); if (monoid().lessThan(m, sig)) { ring().freeMonomial(m); return be; } } ring().freeMonomial(m); return static_cast(-1); } void SigPolyBasis::lowBaseDivisors( std::vector& divisors, size_t maxDivisors, size_t newGenerator) const { MATHICGB_ASSERT(newGenerator < size()); const auto sigNew = signature(newGenerator); const auto component = monoid().component(sigNew); mSignatureLookup[component]-> lowBaseDivisors(divisors, maxDivisors, newGenerator); #ifdef MATHICGB_DEBUG std::vector debugValue; lowBaseDivisorsSlow(debugValue, maxDivisors, newGenerator); MATHICGB_ASSERT(divisors.size() <= maxDivisors); MATHICGB_ASSERT(debugValue.size() == divisors.size()); for (size_t i = 0; i < divisors.size(); ++i) { MATHICGB_ASSERT(ratioCompare(debugValue[i], divisors[i]) == EQ); } #endif } void SigPolyBasis::lowBaseDivisorsSlow( std::vector& divisors, size_t maxDivisors, size_t newGenerator) const { MATHICGB_ASSERT(newGenerator < size()); divisors.clear(); divisors.reserve(maxDivisors + 1); auto sigNew = signature(newGenerator); for (size_t i = 0; i < newGenerator; ++i) { auto sigi = signature(i); if (monoid().component(sigi) != monoid().component(sigNew)) continue; if (!monoid().divides(sigi, sigNew)) continue; for (size_t j = 0; j <= divisors.size(); ++j) { if (j == divisors.size()) { divisors.push_back(i); break; } if (ratioCompare(i, divisors[j]) == GT) { divisors.insert(divisors.begin() + j, i); break; } } if (divisors.size() > maxDivisors) divisors.pop_back(); MATHICGB_ASSERT(divisors.size() <= maxDivisors); } MATHICGB_ASSERT(divisors.size() <= maxDivisors); } size_t SigPolyBasis::highBaseDivisor(size_t newGenerator) const { MATHICGB_ASSERT(newGenerator < size()); size_t highDivisor = monoLookup().highBaseDivisor(newGenerator); #ifdef MATHICGB_DEBUG size_t debugValue = highBaseDivisorSlow(newGenerator); MATHICGB_ASSERT((highDivisor == static_cast(-1)) == (debugValue == static_cast(-1))); MATHICGB_ASSERT(highDivisor == static_cast(-1) || ratioCompare(debugValue, highDivisor) == EQ); #endif return highDivisor; } size_t SigPolyBasis::highBaseDivisorSlow(size_t newGenerator) const { MATHICGB_ASSERT(newGenerator < size()); auto highDivisor = static_cast(-1); auto leadNew = leadMono(newGenerator); for (size_t i = 0; i < newGenerator; ++i) { // continue if this generator would not be an improvement // even if it does divide. This is a faster check than // checking divisiblity, so do it first. if (highDivisor != static_cast(-1) && ratioCompare(highDivisor, i) == LT) continue; auto leadi = leadMono(i); if (monoid().divides(leadi, leadNew)) highDivisor = i; } return highDivisor; } size_t SigPolyBasis::minimalLeadInSig(ConstMonoRef sig) const { const auto component = monoid().component(sig); const auto minLeadGen = mSignatureLookup[component]->minimalLeadInSig(sig); MATHICGB_ASSERT(minLeadGen == minimalLeadInSigSlow(sig)); return minLeadGen; } size_t SigPolyBasis::minimalLeadInSigSlow(ConstMonoRef sig) const { monomial multiplier = ring().allocMonomial(); monomial minLead = ring().allocMonomial(); size_t minLeadGen = static_cast(-1); const auto sigComponent = monoid().component(sig); const size_t genCount = size(); for (size_t gen = 0; gen < genCount; ++gen) { if (monoid().component(signature(gen)) != sigComponent) continue; if (!monoid().divides(signature(gen), sig)) continue; monoid().divide(signature(gen), sig, multiplier); if (minLeadGen != static_cast(-1)) { auto genLead = leadMono(gen); const auto leadCmp = monoid().compare(minLead, multiplier, genLead); if (leadCmp == Monoid::LessThan) continue; if (leadCmp == Monoid::EqualTo) { // If same lead monomial in signature, pick the one with fewer terms // as that one might be less effort to reduce. const size_t minTerms = poly(minLeadGen).termCount(); const size_t terms = poly(gen).termCount(); if (minTerms > terms) continue; if (minTerms == terms) { // If same number of terms, pick the one with larger signature // before being multiplied into the same signature. That one // might be more reduced as the constraint on regular reduction // is less. const auto minSig = signature(minLeadGen); const auto genSig = signature(gen); const auto sigCmp = monoid().compare(minSig, genSig); // no two generators have same signature MATHICGB_ASSERT(sigCmp != Monoid::EqualTo); if (sigCmp == GT) continue; } } } minLeadGen = gen; monoid().multiply(multiplier, leadMono(gen), minLead); } ring().freeMonomial(multiplier); ring().freeMonomial(minLead); return minLeadGen; } bool SigPolyBasis::isSingularTopReducibleSlow( const Poly& poly, ConstMonoRef sig ) const { if (poly.isZero()) return false; monomial multiplier = ring().allocMonomial(); const size_t genCount = size(); const auto polyLead = poly.leadMono(); for (size_t i = 0; i < genCount; ++i) { if (!monoid().divides(leadMono(i), polyLead)) continue; monoid().divide(leadMono(i), polyLead, multiplier); if (monoid().compare(sig, multiplier, signature(i)) == EQ) return true; } ring().freeMonomial(multiplier); return false; } void SigPolyBasis::display(std::ostream& out) const { for (size_t i = 0; i < mBasis.size(); i++) { out << i << " "; // This is needed for compatibility with old tests. // todo: change the tests so this isn't necessary. if (monoid().isIdentity(*mSignatures[i])) MathicIO<>().writeComponent(monoid(), *mSignatures[i], out); else MathicIO<>().writeMonomial(monoid(), true, *mSignatures[i], out); out << " "; MathicIO<>().writePoly(mBasis.poly(i), false, out); out << '\n'; } } void SigPolyBasis::displayFancy (std::ostream& out, const Processor& processor) const { mathic::ColumnPrinter pr; auto& indexOut = pr.addColumn(false) << "Index\n"; auto& sigOut = pr.addColumn(false) << "sig\n"; auto& polyOut = pr.addColumn() << "poly\n"; pr.repeatToEndOfLine('-'); auto sig = monoid().alloc(); for (size_t i = 0; i < mBasis.size(); i++) { indexOut << i << '\n'; monoid().copy(*mSignatures[i], *sig); processor.postprocess(sig); if (monoid().isIdentity(*sig)) MathicIO<>().writeComponent(monoid(), *sig, out); else MathicIO<>().writeMonomial(monoid(), true, *sig, out); sigOut << '\n'; MathicIO<>().writePoly(mBasis.poly(i), false, polyOut); polyOut << '\n'; } out << pr; } void SigPolyBasis::postprocess(const MonoProcessor& processor) { for (auto& mono : mSignatures) processor.postprocess(*mono); } size_t SigPolyBasis::getMemoryUse() const { // Note: we do not count the signatures as they are counted elsewhere. size_t total = 0; total += mBasis.getMemoryUse(); total += mSignatures.capacity() * sizeof(mSignatures.front()); total += mSigLeadRatio.capacity() * sizeof(mSigLeadRatio.front()); total += mRatioRanks.capacity() * sizeof(mRatioRanks.front()); total += monoLookup().getMemoryUse(); total += mMinimalMonoLookup->getMemoryUse(); // This is an estimate of how much memory mRatioSorted uses per item. // It is based on assuming a tree representation with a left pointer, // a right pointer and a data member for each node. This is probably // an underestimate. const size_t perItemOverhead = 2 * sizeof(void*) + sizeof(*mRatioSorted.begin()); total += mRatioSorted.size() * perItemOverhead; return total; } size_t SigPolyBasis::ratioRank(ConstMonoRef ratio) const { MATHICGB_ASSERT(mUseRatioRank); const size_t index = size(); if (index == 0) return 0; // any value will do as there is nothing to compare to auto& sigLeadRatioNonConst = const_cast&>(mSigLeadRatio); sigLeadRatioNonConst.push_back(ratio.castAwayConst()); auto pos = mRatioSorted.lower_bound(index); sigLeadRatioNonConst.pop_back(); if (pos == mRatioSorted.end()) { MATHICGB_ASSERT (ratioRank(*mRatioSorted.rbegin()) < std::numeric_limits::max()); return std::numeric_limits::max(); } else { if (monoid().equal(ratio, sigLeadRatio(*pos))) return ratioRank(*pos); MATHICGB_ASSERT(ratioRank(*pos) > 0); #ifdef MATHICGB_DEBUG if (pos != mRatioSorted.begin()) { auto prev = pos; --prev; MATHICGB_ASSERT(ratioRank(*pos) - 1 > ratioRank(*prev)); } #endif return ratioRank(*pos) - 1; } } SigPolyBasis::StoredRatioCmp::StoredRatioCmp( ConstMonoRef numerator, ConstMonoRef denominator, const SigPolyBasis& basis ): mBasis(basis), mRatio(basis.monoid().alloc()) { const auto& monoid = basis.ring().monoid(); monoid.divideToNegative(denominator, numerator, mRatio); if (SigPolyBasis::mUseRatioRank) mRatioRank = basis.ratioRank(*mRatio); else mTmp = mBasis.monoid().alloc(); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/SigPolyBasis.hpp000077500000000000000000000204511311555162500215640ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SIG_POLY_BASIS_GUARD #define MATHICGB_SIG_POLY_BASIS_GUARD #include "PolyRing.hpp" #include "Poly.hpp" #include "MonoLookup.hpp" #include "PolyBasis.hpp" #include "MonoProcessor.hpp" #include #include MATHICGB_NAMESPACE_BEGIN #ifndef MATHICGB_USE_RATIO_RANK #define MATHICGB_USE_RATIO_RANK true #endif /// Stores a basis of polynomials that each have a signature. Designed for /// use in signature Groebner basis algorithms. class SigPolyBasis { public: typedef PolyRing::Field Field; typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef MonoProcessor Processor; SigPolyBasis( const PolyRing& R, int monoLookupType, int monTableType, bool preferSparseReducers ); ~SigPolyBasis(); const PolyRing& ring() const {return mBasis.ring();} const Monoid& monoid() const {return ring().monoid();} const Field& field() const {return ring().field();} const Poly& poly(size_t index) const {return mBasis.poly(index);} size_t size() const {return mBasis.size();} const PolyBasis& basis() const {return mBasis;} ConstMonoRef leadMono(size_t gen) const { MATHICGB_ASSERT(gen < size()); return mBasis.leadMono(gen); } coefficient leadCoef(size_t gen) const { MATHICGB_ASSERT(gen < size()); return mBasis.leadCoef(gen); } ConstMonoRef sigLeadRatio(size_t gen) const { MATHICGB_ASSERT(gen < size()); return *mSigLeadRatio[gen]; } // Signifies that the module has taken on another e_i. // Must call this before adding a polynomial to the basis with // a signature in the new component. void addComponent(); // Takes over ownership of sig and f. sig must come from the pool // of ring(). void insert(Mono sig, std::unique_ptr f); ConstMonoRef signature(size_t gen) const { MATHICGB_ASSERT(gen < size()); return *mSignatures[gen]; } // Returns the index of a basis element that regular reduces term in // signature sig. Returns -1 if no such element exists. A basis element // u is a regular reducer if leadTerm(u) divides term // and (term / leadTerm(u)) * signature(u) < sig. size_t regularReducer(ConstMonoRef sig, ConstMonoRef term) const; // Uses the functionality in the divisor finder for // computing up to maxDivisors low ratio base divisors. // The divisors are placed into divisors. void lowBaseDivisors( std::vector& divisors, size_t maxDivisors, size_t newGenerator ) const; // Uses the functionality in the divisor finder for // computing a high base divisor. Returns the index // of the divisor or -1 if none are found. size_t highBaseDivisor(size_t newGenerator) const; // Find the basis element g_i whose signature S divides sig // such that (S/sig)g_i has minimal leading term. Returns i. size_t minimalLeadInSig(ConstMonoRef sig) const; // Returns true if poly can be singular reduced in signature sig. // In other words, returns true if there is a basis element with // lead term M and signature S such that M divides the lead term N // of poly and such that N/M*S == sig. This is slow because it is // currently only used for asserts - implement a fast version if // that changes. bool isSingularTopReducibleSlow(const Poly& poly, ConstMonoRef sig) const; void display(std::ostream& out) const; void displayFancy(std::ostream& out, const Processor& processor) const; size_t getMemoryUse() const; // Compares the signature/lead ratio of basis element a to basis element b // and returns LT, EQ or GT. inline int ratioCompare(size_t a, size_t b) const; /// Post processes all signatures. This currently breaks all sorts /// of internal invariants - it's supposed to be a temporary hack. void postprocess(const Processor& processor); class StoredRatioCmp { public: // Stores the ratio numerator/denominator and prepares it for comparing // to the sig/lead ratios in basis. StoredRatioCmp( ConstMonoRef numerator, ConstMonoRef denominator, const SigPolyBasis& basis); // compares the stored ratio to the basis element with index be. inline int compare(size_t be) const; private: StoredRatioCmp(const StoredRatioCmp&); // not available void operator=(const StoredRatioCmp&); // not available const SigPolyBasis& mBasis; size_t mRatioRank; Mono mRatio; mutable Mono mTmp; }; private: // Slow versions use simpler code. Used to check results in debug mode. size_t regularReducerSlow(ConstMonoRef sig, ConstMonoRef term) const; size_t minimalLeadInSigSlow(ConstMonoRef sig) const; size_t highBaseDivisorSlow(size_t newGenerator) const; void lowBaseDivisorsSlow( std::vector& divisors, size_t maxDivisors, size_t newGenerator ) const; friend class StoredRatioCmp; const MonoLookup& monoLookup() const {return mBasis.monoLookup();} std::unique_ptr const mMonoLookupFactory; /// The ratio rank can change at each insert! size_t ratioRank(size_t index) const { MATHICGB_ASSERT(index < size()); return mRatioRanks[index]; } // Only useful for comparing to basis elements. Two ratios might get the same // rank without being equal. All ranks can change when a new generator // is added. size_t ratioRank(ConstMonoRef ratio) const; std::vector mSignatures; // the ratio signature/initial term including negative entries and module component std::vector mSigLeadRatio; // true if giving each generator an integer id based on its // position in a sorted order of sig-lead ratios. static const bool mUseRatioRank = MATHICGB_USE_RATIO_RANK; static const bool mUseStoredRatioRank = MATHICGB_USE_RATIO_RANK; class RatioOrder { public: RatioOrder(std::vector& ratio, const Monoid& monoid): mRatio(ratio), mMonoid(monoid) {} bool operator()(size_t a, size_t b) const { return mMonoid.lessThan(*mRatio[a], *mRatio[b]); } private: std::vector& mRatio; const Monoid& mMonoid; }; typedef std::multiset RatioSorted; typedef size_t Rank; RatioSorted mRatioSorted; std::vector mRatioRanks; std::vector mSignatureLookup; // Contains those lead terms that are minimal. std::unique_ptr const mMinimalMonoLookup; PolyBasis mBasis; bool const mPreferSparseReducers; mutable monomial mTmp; }; inline int SigPolyBasis::ratioCompare(size_t a, size_t b) const { if (mUseRatioRank) { #ifdef MATHICGB_DEBUG int const value = monoid().compare(sigLeadRatio(a), sigLeadRatio(b)); #endif if (mRatioRanks[a] < mRatioRanks[b]) { MATHICGB_ASSERT_NO_ASSUME(value == LT); return LT; } else if (mRatioRanks[a] > mRatioRanks[b]) { MATHICGB_ASSERT_NO_ASSUME(value == GT); return GT; } else { MATHICGB_ASSERT_NO_ASSUME(value == EQ); return EQ; } } else { // A/a < B/b <=> A < (B/b)a monoid().divideToNegative(signature(b), leadMono(b), mTmp); monoid().multiplyInPlace(leadMono(a), mTmp); const auto value = monoid().compare(signature(a), mTmp); MATHICGB_ASSERT (value == monoid().compare(sigLeadRatio(a), sigLeadRatio(b))); return value; } } inline int SigPolyBasis::StoredRatioCmp::compare(size_t be) const { if (SigPolyBasis::mUseStoredRatioRank) { #ifdef MATHICGB_DEBUG const auto value = mBasis.monoid().compare(*mRatio, mBasis.sigLeadRatio(be)); #endif SigPolyBasis::Rank otherRank = mBasis.ratioRank(be); if (mRatioRank < otherRank) { MATHICGB_ASSERT_NO_ASSUME(value == LT); return LT; } else if (mRatioRank > otherRank) { MATHICGB_ASSERT_NO_ASSUME(value == GT); return GT; } else { MATHICGB_ASSERT_NO_ASSUME(value == EQ); return EQ; } } else { mBasis.monoid().multiply(*mRatio, mBasis.leadMono(be), *mTmp); const auto value = mBasis.monoid().compare(*mTmp, mBasis.signature(be)); MATHICGB_ASSERT (value == mBasis.monoid().compare(*mRatio, mBasis.sigLeadRatio(be))); return value; } } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/SigSPairQueue.cpp000077500000000000000000000144001311555162500216720ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "SigSPairQueue.hpp" #include "SigPolyBasis.hpp" MATHICGB_NAMESPACE_BEGIN SigSPairQueue::~SigSPairQueue() {} namespace { class Comparer { public: typedef PolyRing::Monoid Monoid; Comparer(const Monoid& monoid): mMonoid(monoid) {} bool operator()(const PreSPair& a, const PreSPair& b) const { return mMonoid.lessThan(*a.signature, *b.signature); } private: const Monoid& mMonoid; }; // Iterator that accesses the field i based on a passed-in iterator. template class IndexIterator { public: typedef typename PairIterator::iterator_category iterator_category; typedef decltype(reinterpret_cast(0)->i) value_type; typedef typename PairIterator::difference_type difference_type; typedef value_type* pointer; typedef value_type& reference; IndexIterator(PairIterator pairIterator): mIterator(pairIterator) {} IndexIterator& operator++() {++mIterator; return *this;} const value_type operator*() const {return mIterator->i;} difference_type operator-(const IndexIterator& it) const { return mIterator - it.mIterator; } bool operator==(const IndexIterator& it) const { return mIterator == it.mIterator; } bool operator!=(const IndexIterator& it) const { return mIterator != it.mIterator; } private: PairIterator mIterator; }; } class ConcreteSigSPairQueue : public SigSPairQueue { public: ConcreteSigSPairQueue(SigPolyBasis const& basis): mPairQueue(Configuration(basis)) {} virtual Mono popSignature(Pairs& pairs) { pairs.clear(); if (mPairQueue.empty()) return 0; auto sig = monoid().alloc(); monoid().copy(*mPairQueue.topPairData(), *sig); do { pairs.push_back(mPairQueue.topPair()); mPairQueue.pop(); } while ( !mPairQueue.empty() && monoid().equal(*mPairQueue.topPairData(), *sig) ); return sig; } virtual void pushPairs(size_t pairWith, IndexSigs& pairs) { #ifdef DEBUG { auto tmp = monoid().alloc(); for (size_t i = 0; i < pairs.size(); ++i) { MATHICGB_ASSERT(pairs[i].i < columnCount()); mPairQueue.configuration().computePairData (columnCount(), pairs[i].i, tmp.ptr()); MATHICGB_ASSERT(monoid().equal(*tmp, *pairs[i].signature)); } } #endif if (columnCount() >= std::numeric_limits::max()) throw std::overflow_error ("Too large basis element index in constructing S-pairs."); // sort and insert new column Comparer cmp(ring().monoid()); std::sort(pairs.begin(), pairs.end(), cmp); typedef IndexIterator::const_iterator> Iter; mPairQueue.addColumnDescending(Iter(pairs.begin()), Iter(pairs.end())); // free signatures for (auto& spair : pairs) monoid().freeRaw(spair.signature); pairs.clear(); } virtual std::string name() const {return "todo";} virtual size_t memoryUse() const {return mPairQueue.getMemoryUse();} virtual size_t pairCount() const {return mPairQueue.pairCount();} virtual size_t columnCount() const {return mPairQueue.columnCount();} private: ConcreteSigSPairQueue(const ConcreteSigSPairQueue&); // not available void operator=(const ConcreteSigSPairQueue&); // not available // Configuration of mathic::PairTriangle for use with signature queues. class Configuration { public: Configuration(SigPolyBasis const& basis): mBasis(basis) {} typedef MonoPtr PairData; void computePairData(size_t col, size_t row, PairData sig) { MATHICGB_ASSERT(mBasis.ratioCompare(col, row) != EQ); // ensure that ratio(col) > ratio(row) if (mBasis.ratioCompare(col, row) == LT) std::swap(col, row); monoid().colonMultiply( mBasis.leadMono(col), mBasis.leadMono(row), mBasis.signature(col), *sig ); } typedef bool CompareResult; bool compare(int colA, int rowA, PairData a, int colB, int rowB, PairData b) const { return mBasis.ring().monoid().lessThan(*b, *a); } bool cmpLessThan(bool v) const {return v;} SigPolyBasis const& basis() const {return mBasis;} const PolyRing& ring() const {return basis().ring();} const Monoid& monoid() const {return ring().monoid();} private: SigPolyBasis const& mBasis; }; // the compiler should be able to resolve these accessors into a direct // offset as though these were member variables. const SigPolyBasis& basis() const { return mPairQueue.configuration().basis(); } const PolyRing& ring() const {return basis().ring();} const Monoid& monoid() const {return ring().monoid();} mathic::PairQueue mPairQueue; friend struct mathic::PairQueueNamespace::ConstructPairDataFunction; friend struct mathic::PairQueueNamespace::DestructPairDataFunction; }; std::unique_ptr SigSPairQueue::create( SigPolyBasis const& basis ) { return make_unique(basis); } MATHICGB_NAMESPACE_END namespace mathic { namespace PairQueueNamespace { template<> struct ConstructPairDataFunction { inline static void function( void* memory, Index col, Index row, mgb::ConcreteSigSPairQueue::Configuration& conf ) { MATHICGB_ASSERT(memory != 0); MATHICGB_ASSERT(col > row); auto pd = new (memory) mgb::ConcreteSigSPairQueue::Configuration::PairData (conf.basis().ring().allocMonomial()); conf.computePairData(col, row, *pd); } }; template<> struct DestructPairDataFunction { inline static void function( mgb::ConcreteSigSPairQueue::Configuration::PairData* pd, Index col, Index row, mgb::ConcreteSigSPairQueue::Configuration& conf ) { MATHICGB_ASSERT(pd != nullptr); MATHICGB_ASSERT(col > row); conf.monoid().freeRaw(*pd); } }; } } mathicgb-master/src/mathicgb/SigSPairQueue.hpp000077500000000000000000000055361311555162500217110ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SIG_S_PAIR_QUEUE_GUARD #define MATHICGB_SIG_S_PAIR_QUEUE_GUARD #include "PolyRing.hpp" #include #include MATHICGB_NAMESPACE_BEGIN typedef unsigned short SmallIndex; typedef unsigned int BigIndex; struct PreSPair { BigIndex i; PolyRing::Monoid::MonoPtr signature; }; class SigPolyBasis; // A priority queue on S-pairs where the priority is based on a // signature as in signature Grobner basis algorithms. The class is // not responsible for eliminating S-pairs or doing anything beyond // order the S-pairs. class SigSPairQueue { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; virtual ~SigSPairQueue(); typedef std::pair Pair; typedef std::vector Pairs; //typedef std::pair IndexSig; typedef PreSPair IndexSig; typedef std::vector IndexSigs; // Takes the minimal signature in the queue and adds all S-pairs of // that signature to pairs. Clears pairs first. Returns null and // leaves pairs empty if the queue is empty. // // This class does not have an empty() method on purpose - you are // supposed to call this method until it returns null. virtual Mono popSignature(Pairs& pairs) = 0; // If (x, sig) is an element of pairsConsumed then (pairWith, x) is // added to the queue. sig must be the signature of the S-pair // (pairWith, x). // // ATTENTION: the calls to pushPairs must have pairWith in the // sequence 0, 1, 2, 3 and so on. It follows from this that the // queue can figure out what pairWith is without being told. Thus // the purpose of pairWith is to make it possible to make an // assertion saying that the caller and the queue agree on what // pairWith is. // // ATTENTION: pairsConsumed will be cleared and the signatures in it // will be freed on the ring. This is because the queue will need to // alter pairsConsumed in various ways and clearing it after that is // cleaner than exposing what's being done to // pairsConsumed. Especially since after you did pushPairs there // would not be a reason to care about what its content was. virtual void pushPairs(size_t pairWith, IndexSigs& pairsConsumed) = 0; // Returns a string that describes the queue. virtual std::string name() const = 0; // Returns the number of pairs currently in the queue. virtual size_t pairCount() const = 0; // Returns number of bytes of memory used. virtual size_t memoryUse() const = 0; static std::unique_ptr create(SigPolyBasis const& basis); }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/SigSPairs.cpp000077500000000000000000000237731311555162500210650ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "SigSPairs.hpp" #include "SigPolyBasis.hpp" #include "ModuleMonoSet.hpp" #include "Reducer.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN SigSPairs::SigSPairs( const PolyRing *R0, const SigPolyBasis *GB0, ModuleMonoSet *Hsyz0, Reducer* reducer, bool postponeKoszuls, bool useBaseDivisors, bool useSingularCriterionEarly, size_t queueType ): R(R0), mUseSingularCriterionEarly(useSingularCriterionEarly), mUseBaseDivisors(useBaseDivisors), mUseHighBaseDivisors(useBaseDivisors), Hsyz(Hsyz0), GB(GB0), mReducer(reducer), mPostponeKoszuls(postponeKoszuls), mQueue(SigSPairQueue::create(*GB)) {} SigSPairs::~SigSPairs() { MATHICGB_ASSERT(mUseBaseDivisors || mUseHighBaseDivisors || mKnownSyzygyTri.empty()); } auto SigSPairs::popSignature(PairContainer& pairs) -> Mono { auto sig = mQueue->popSignature(pairs); if (!sig.isNull()) { size_t const pairCount = pairs.size(); mStats.spairsFinal += pairCount; mStats.duplicateSignatures += pairCount - 1; } return sig; } void SigSPairs::newPairs(size_t newGen) { MATHICGB_ASSERT(mIndexSigs.empty()); makePreSPairs(newGen); mQueue->pushPairs(newGen, mIndexSigs); mIndexSigs.clear(); MATHICGB_ASSERT((!mUseBaseDivisors && !mUseHighBaseDivisors) || mKnownSyzygyTri.columnCount() == newGen + 1); } void SigSPairs::setupBaseDivisors( BaseDivisor& divisor1, BaseDivisor& divisor2, size_t& highDivisorCmp, size_t newGenerator ) { BaseDivContainer divisors; const size_t MaxBaseDivisors = 2; if (mUseBaseDivisors || mUseHighBaseDivisors) divisors.reserve(MaxBaseDivisors + 1); MATHICGB_ASSERT(mUseBaseDivisors || mUseHighBaseDivisors); MATHICGB_ASSERT(mKnownSyzygyTri.columnCount() == newGenerator); mKnownSyzygyTri.addColumn(); if (mUseHighBaseDivisors) { size_t highDivisor = GB->highBaseDivisor(newGenerator); if (highDivisor != static_cast(-1)) { // To use a high divisor, the ratio of the other generator has to be // greater than both the ratio of newGenerator and of the high ratio // divisor. We can check both at once by letting highDivisorCmp // be the one out of newGenerator and highDivisor that has the // highest ratio. if (GB->ratioCompare(newGenerator, highDivisor) == GT) highDivisorCmp = newGenerator; else highDivisorCmp = highDivisor; } } else highDivisorCmp = static_cast(-1); if (!mUseBaseDivisors) return; std::vector divs; GB->lowBaseDivisors(divs, MaxBaseDivisors, newGenerator); MATHICGB_ASSERT(divs.size() <= MaxBaseDivisors); divisors.resize(divs.size()); for (size_t i = 0; i < divisors.size(); ++i) { BaseDivisor& bd = divisors[i]; bd.baseDivisor = divs[i]; // Only use the base divisor technique for generators with ratio // less than both N and baseDivisor. baseDivisorCmp is the // smallest one of these, so it can be used for this comparison. if (GB->ratioCompare(newGenerator, bd.baseDivisor) == LT) bd.ratioLessThan = newGenerator; else bd.ratioLessThan = bd.baseDivisor; // Construct a monomial in makeSPair_t2 that can be used // to eliminate s-pairs quickly based on the s-pairs already // eliminated for baseDivisor. auto newSig = GB->signature(newGenerator); auto newLead = GB->leadMono(newGenerator); auto baseDivSig = GB->signature(bd.baseDivisor); auto baseDivLead = GB->leadMono(bd.baseDivisor); bd.baseMonomial = R->allocMonomial(); R->mysteriousSPairMonomialRoutine( Monoid::toOld(newSig), Monoid::toOld(newLead), Monoid::toOld(baseDivSig), Monoid::toOld(baseDivLead), bd.baseMonomial ); } divisor1.baseDivisor = static_cast(-1); divisor2.baseDivisor = static_cast(-1); if (divisors.size() >= 1) divisor1 = divisors.front(); if (divisors.size() == 2) { divisor2 = divisors.back(); MATHICGB_ASSERT(GB->ratioCompare (divisor1.ratioLessThan, divisor2.ratioLessThan) != LT); } } void SigSPairs::makePreSPairs(size_t newGen) { MATHICGB_ASSERT(mIndexSigs.empty()); MATHICGB_ASSERT(newGen < GB->size()); mStats.spairsConstructed += newGen; monomial baseDivisorMonomial = 0; BaseDivisor divisor1; BaseDivisor divisor2; divisor1.baseDivisor = static_cast(-1); divisor2.baseDivisor = static_cast(-1); size_t highDivisorCmp = static_cast(-1); if (mUseBaseDivisors || mUseHighBaseDivisors) setupBaseDivisors(divisor1, divisor2, highDivisorCmp, newGen); monomial hsyz = 0; if (!mPostponeKoszuls) hsyz = R->allocMonomial(); auto newSig = GB->signature(newGen); auto newLead = GB->leadMono(newGen); auto pairSig = R->allocMonomial(); if (mUseHighBaseDivisors && divisor1.baseDivisor != static_cast(-1)) ++mStats.hasLowBaseDivisor; if (mUseHighBaseDivisors && highDivisorCmp != static_cast(-1)) ++mStats.hasHighBaseDivisor; PreSPair result; for (size_t oldGen = 0; oldGen < newGen; oldGen++) { auto oldSig = GB->signature(oldGen); auto oldLead = GB->leadMono(oldGen); // Check whether this is a non-regular spair. // 'cmp' is used below too. const int cmp = GB->ratioCompare(newGen, oldGen); if (cmp == EQ) { ++mStats.nonregularSPairs; continue; } // check high ratio divisor if (mUseHighBaseDivisors && highDivisorCmp != static_cast(-1) && GB->ratioCompare(oldGen, highDivisorCmp) == GT && mKnownSyzygyTri.bitUnordered(oldGen, highDivisorCmp)) { MATHICGB_ASSERT(oldGen != highDivisorCmp); // otherwise ratios should be equal mKnownSyzygyTri.setBit(newGen, oldGen, true); ++mStats.highBaseDivisorHits; // if DEBUG defined, get to the ASSERT below stating // that this is really a syzygy #ifndef DEBUG continue; #endif } // check low ratio divisors if (mUseBaseDivisors && divisor1.baseDivisor != static_cast(-1) && GB->ratioCompare(oldGen, divisor1.ratioLessThan) == LT) { // if no divisor1, also no divisor 2 and also // divisor1 has larger ratio, so skip both checks if divisor1 fails due // to the ratio being too small or because there is no divisor1. if ( (divisor1.baseDivisor != oldGen && // if divisor1 is a hit mKnownSyzygyTri.bitUnordered(divisor1.baseDivisor, oldGen) && monoid().divides(oldLead, divisor1.baseMonomial)) || // or if divisor2 is a hit (divisor2.baseDivisor != static_cast(-1) && GB->ratioCompare(oldGen, divisor2.ratioLessThan) == LT && divisor2.baseDivisor != oldGen && mKnownSyzygyTri.bitUnordered(divisor2.baseDivisor, oldGen) && monoid().divides(oldLead, divisor2.baseMonomial)) ) { mKnownSyzygyTri.setBit(newGen, oldGen, true); ++mStats.lowBaseDivisorHits; // if DEBUG defined, get to the ASSERT below stating // that this really is a syzygy. #ifndef DEBUG continue; #endif } } if (cmp == GT) monoid().colonMultiply(newLead, oldLead, newSig, pairSig); else { MATHICGB_ASSERT(cmp == LT); monoid().colonMultiply(oldLead, newLead, oldSig, pairSig); } if (Hsyz->member(pairSig)) { ++mStats.syzygyModuleHits; #ifdef DEBUG // Check if actually already elim. by low/high base divisor. // Only check in DEBUG mode as otherwise we would have taken an early // exit before getting here. if ((mUseBaseDivisors || mUseHighBaseDivisors) && mKnownSyzygyTri.bit(newGen, oldGen)) --mStats.syzygyModuleHits; #endif if (mUseBaseDivisors || mUseHighBaseDivisors) mKnownSyzygyTri.setBit(newGen, oldGen, true); continue; } MATHICGB_ASSERT((!mUseBaseDivisors && !mUseHighBaseDivisors) || !mKnownSyzygyTri.bit(newGen, oldGen)); if (!mPostponeKoszuls) { // add koszul syzygy to Hsyz. MATHICGB_ASSERT(cmp == GT || cmp == LT); if (cmp == GT) monoid().multiply(newSig, oldLead, hsyz); else monoid().multiply(oldSig, newLead, hsyz); if (Hsyz->insert(hsyz)) hsyz = R->allocMonomial(); if (monoid().relativelyPrime(newLead, oldLead)) { ++mStats.earlyRelativelyPrimePairs; continue; } } if (mUseSingularCriterionEarly) { MATHICGB_ASSERT(cmp == GT || cmp == LT); size_t const givesSig = (cmp == GT ? newGen : oldGen); if ( GB->ratioCompare(GB->minimalLeadInSig(pairSig), givesSig) == GT && !monoid().relativelyPrime(newLead, oldLead) ) { ++mStats.earlySingularCriterionPairs; continue; } } // construct the PreSPair result.signature = pairSig; pairSig = R->allocMonomial(); result.i = static_cast(oldGen); mIndexSigs.push_back(result); ++mStats.queuedPairs; } R->freeMonomial(pairSig); if (mUseBaseDivisors && ! baseDivisorMonomial.isNull()) R->freeMonomial(baseDivisorMonomial); if (!mPostponeKoszuls) R->freeMonomial(hsyz); } void SigSPairs::setKnownSyzygies(std::vector >& pairs) { if (!mUseBaseDivisors && !mUseHighBaseDivisors) return; for (size_t i = 0; i < pairs.size(); ++i) setKnownSyzygy(pairs[i].first, pairs[i].second); } void SigSPairs::setKnownSyzygy(size_t gen1, size_t gen2) { MATHICGB_ASSERT(gen1 < GB->size()); MATHICGB_ASSERT(gen2 < GB->size()); MATHICGB_ASSERT(gen1 != gen2); if (mUseBaseDivisors || mUseHighBaseDivisors) mKnownSyzygyTri.setBitUnordered(gen1, gen2, true); } size_t SigSPairs::pairCount() const { return mQueue->pairCount(); } std::string SigSPairs::name() { return mQueue->name(); } size_t SigSPairs::getMemoryUse() const { return mQueue->memoryUse() + getKnownSyzygyBitsMemoryUse(); } size_t SigSPairs::getKnownSyzygyBitsMemoryUse() const { return mKnownSyzygyTri.getMemoryUse(); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/SigSPairs.hpp000077500000000000000000000106011311555162500210540ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SIG_S_PAIRS_GUARD #define MATHICGB_SIG_S_PAIRS_GUARD #include "PolyRing.hpp" #include "KoszulQueue.hpp" #include "SigSPairQueue.hpp" #include #include #include MATHICGB_NAMESPACE_BEGIN class Poly; class ModuleMonoSet; class SigPolyBasis; class Reducer; // Handles S-pairs in signature Grobner basis algorithms. Responsible // for eliminating S-pairs, storing S-pairs and ordering S-pairs. class SigSPairs { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::MonoRef MonoRef; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::MonoPtr MonoPtr; typedef Monoid::ConstMonoPtr ConstMonoPtr; SigSPairs( const PolyRing *R0, const SigPolyBasis *GB0, ModuleMonoSet *Hsyz0, Reducer* reducer, bool postponeKoszuls, bool useBaseDivisors, bool useSingularCriterionEarly, size_t queueType); ~SigSPairs(); typedef std::vector > PairContainer; Mono popSignature(PairContainer& pairs); // fills in all the S-pairs with i. void newPairs(size_t i); struct Stats { unsigned long long spairsConstructed; // all spairs unsigned long long spairsFinal; // spairs given to client unsigned long long nonregularSPairs; // spairs eliminated by being non-regular unsigned long long highBaseDivisorHits; // spairs eliminated by high base divisor unsigned long long lowBaseDivisorHits; // spairs eliminated by low base divisor unsigned long long hasHighBaseDivisor; // generators that have a high base divisor unsigned long long hasLowBaseDivisor; // generators that have a low base divisor unsigned long long syzygyModuleHits; // spairs eliminated by syzygy module unsigned long long earlyRelativelyPrimePairs; unsigned long long earlySingularCriterionPairs; unsigned long long queuedPairs; // number actually placed on spair triangle unsigned long long duplicateSignatures; // number of spairs removed due to duplicate signature Stats(): spairsConstructed(0), spairsFinal(0), nonregularSPairs(0), highBaseDivisorHits(0), lowBaseDivisorHits(0), hasHighBaseDivisor(0), hasLowBaseDivisor(0), syzygyModuleHits(0), earlyRelativelyPrimePairs(0), earlySingularCriterionPairs(0), queuedPairs(0), duplicateSignatures(0) {} }; Stats getStats() const {return mStats;} size_t pairCount() const; size_t getMemoryUse() const; size_t getKnownSyzygyBitsMemoryUse() const; // Informs the s-pair handler that the syzygy between gen1 and gen2 // is a known syzygy. void setKnownSyzygy(size_t gen1, size_t gen2); void setKnownSyzygies(std::vector >& pairs); const PolyRing& ring() {return *R;} const Monoid& monoid() {return ring().monoid();} std::string name(); private: void makePreSPairs(size_t newGen); struct BaseDivisor { // a low ratio base divisor size_t baseDivisor; // the index of the generator that is the base divisor size_t ratioLessThan; // consider generators with ratio less than this monomial baseMonomial; // the monomial that has to divide to get a hit }; typedef std::vector BaseDivContainer; void setupBaseDivisors( BaseDivisor& divisor1, BaseDivisor& divisor2, size_t& highDivisorCmp, size_t newGenerator); const PolyRing *R; // if true, apply the early singular criterion bool const mUseSingularCriterionEarly; // true if low ratio base divisors are used to speed up S-pair elimination. const bool mUseBaseDivisors; // True if high ratio base divisors are used to speed up S-pair elimination. // The syzygy should have already been inserted into the syzygy module. const bool mUseHighBaseDivisors; // one entry for every s-pair, which is set to true if the // s-pair is known to be a syzygy. Only used if // mUseBaseDivisors is true. mathic::BitTriangle mKnownSyzygyTri; // From elsewhere ModuleMonoSet *Hsyz; // we often modify this const SigPolyBasis *GB; Reducer* mReducer; const bool mPostponeKoszuls; typedef std::vector PrePairContainer; std::unique_ptr mQueue; SigSPairQueue::IndexSigs mIndexSigs; mutable Stats mStats; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/SignatureGB.cpp000077500000000000000000000564031311555162500213670ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "SignatureGB.hpp" #include "Basis.hpp" #include "MonoLookup.hpp" #include "SigSPairs.hpp" #include "ModuleMonoSet.hpp" #include "LogDomain.hpp" #include #include MATHICGB_DEFINE_LOG_DOMAIN( SigBasisChanged, "Show the signature basis after each change." ); MATHICGB_DEFINE_LOG_DOMAIN( SigSPairFinal, "Show the outcome of final processing for S-pairs." ); MATHICGB_NAMESPACE_BEGIN int tracingLevel = 0; SignatureGB::SignatureGB( Basis&& basis, Processor&& processor, Reducer::ReducerType reductiontyp, int divlookup_type, int montable_type, bool postponeKoszul, bool useBaseDivisors, bool preferSparseReducers, bool useSingularCriterionEarly, size_t queueType ): mBreakAfter(0), mPrintInterval(0), R(basis.getPolyRing()), mPostponeKoszul(postponeKoszul), mUseBaseDivisors(useBaseDivisors), stats_sPairSignaturesDone(0), stats_sPairsDone(0), stats_koszulEliminated(0), stats_SignatureCriterionLate(0), stats_relativelyPrimeEliminated(0), stats_pairsReduced(0), stats_nsecs(0.0), GB(make_unique(*R, divlookup_type, montable_type, preferSparseReducers)), mKoszuls(R->monoid()), Hsyz(ModuleMonoSet::make(R->monoid(), montable_type, basis.size(), !mPostponeKoszul)), Hsyz2(ModuleMonoSet::make(R->monoid(), montable_type, basis.size(), !mPostponeKoszul)), reducer(Reducer::makeReducer(reductiontyp, *R)), SP(make_unique(R, GB.get(), Hsyz.get(), reducer.get(), mPostponeKoszul, mUseBaseDivisors, useSingularCriterionEarly, queueType)) { mProcessor = make_unique>(std::move(processor)); if (basis.size() > std::numeric_limits::max()) mathic::reportError("Dimension of module too large."); const auto componentCount = Component(basis.size()); mProcessor->setComponentCount(componentCount); // Populate GB for (Component j = 0; j < componentCount; j++) GB->addComponent(); for (Component i = 0; i < componentCount; i++) { auto g = make_unique(*basis.getPoly(i)); g->makeMonic(); auto sig = monoid().alloc(); monoid().setIdentity(*sig); monoid().setComponent(i, *sig); mProcessor->preprocess(*sig); GB->insert(std::move(sig), std::move(g)); } // Populate SP for (size_t i = 0; i < basis.size(); i++) SP->newPairs(i); } void SignatureGB::computeGrobnerBasis() { size_t counter = 0; mTimer.reset(); std::ostream& out = std::cout; while (step()) { if (mBreakAfter > 0 && GB->size() > mBreakAfter) { break; const size_t pairs = SP->pairCount(); size_t sigs = 0; size_t syzygySigs = 0; while (true) { auto sig = SP->popSignature(mSpairTmp); if (sig.isNull()) break; ++sigs; if (Hsyz->member(*sig)) ++syzygySigs; else GB->minimalLeadInSig(*sig); } const double syzygyRatio = static_cast(syzygySigs) / sigs; std::cerr << "*** Early exit statistics ***\n" << "remaining spairs: " << pairs << '\n' << "remaining spair signatures: " << sigs << '\n' << "spair signature syzygies: " << syzygySigs << " (" << syzygyRatio * 100 << "% of sigs)\n"; break; } if (mPrintInterval == 0 || (++counter % mPrintInterval) != 0) continue; out << "\n-------------------------------------------------------------\n"; displayMemoryUse(out); out << "\n"; displaySomeStats(out); } // exit(1); /*displayMemoryUse(std::cout); std::cout << "\n"; displaySomeStats(std::cout);*/ // displayMemoryUse(std::cout); stats_nsecs = mTimer.getMilliseconds() / 1000.0; //GB->displayBrief(out); if (mProcessor->processingNeeded()) { GB->postprocess(*mProcessor); Hsyz->forAll([&](ConstMonoRef mono) { auto sig = R->allocMonomial(); R->monoid().copy(mono, sig); mProcessor->postprocess(sig); Hsyz2->insert(sig); }); } } bool SignatureGB::processSPair (Mono sig, const SigSPairs::PairContainer& pairs) { MATHICGB_ASSERT(!pairs.empty()); // the module term to reduce is multiple * GB->getSignature(gen) size_t gen = GB->minimalLeadInSig(*sig); MATHICGB_ASSERT(gen != static_cast(-1)); monomial multiple = R->allocMonomial(); monoid().divide(GB->signature(gen), *sig, multiple); GB->basis().usedAsStart(gen); // reduce multiple * GB->getSignature(gen) auto f = reducer->regularReduce(*sig, multiple, gen, *GB); R->freeMonomial(multiple); if (f == nullptr) { // singular reduction MATHICGB_LOG(SigSPairFinal) << " eliminated by singular criterion.\n"; return true; } if (f->isZero()) { // reduction to zero // todo: what are the correct ownership relations here? auto ptr = sig.release(); Hsyz->insert(*ptr); SP->setKnownSyzygies(mSpairTmp); MATHICGB_LOG(SigSPairFinal) << " s-reduced to zero.\n"; return false; } // new basis element MATHICGB_ASSERT(!GB->isSingularTopReducibleSlow(*f, *sig)); GB->insert(std::move(sig), std::move(f)); MATHICGB_LOG(SigSPairFinal) << " s-reduced to new basis element.\n"; MATHICGB_IF_STREAM_LOG(SigBasisChanged) { stream << "New signature basis element. The basis is now:\n"; GB->displayFancy(stream, *mProcessor); }; SP->newPairs(GB->size()-1); return true; } bool SignatureGB::step() { auto sig = SP->popSignature(mSpairTmp); if (sig.isNull()) return false; ++stats_sPairSignaturesDone; stats_sPairsDone += mSpairTmp.size(); MATHICGB_IF_STREAM_LOG(SigSPairFinal) { stream << "Final processing of signature "; R->monomialDisplay(stream, Monoid::toOld(*sig)); stream << '\n'; }; if (Hsyz->member(*sig)) { ++stats_SignatureCriterionLate; SP->setKnownSyzygies(mSpairTmp); MATHICGB_LOG(SigSPairFinal) << " eliminated by signature criterion.\n"; return true; } while (!mKoszuls.empty() && R->monoid().lessThan(mKoszuls.top(), *sig)) mKoszuls.pop(); if (!mKoszuls.empty() && R->monoid().equal(mKoszuls.top(), *sig)) { ++stats_koszulEliminated; // This signature is of a syzygy that is not in Hsyz, so add it // todo: what are the correct ownership relations here? auto ptr = sig.release(); Hsyz->insert(*ptr); SP->setKnownSyzygies(mSpairTmp); MATHICGB_LOG(SigSPairFinal) << " eliminated by Koszul criterion.\n"; return true; } if (mPostponeKoszul) { // Relatively prime check for (auto it = mSpairTmp.begin(); it != mSpairTmp.end(); ++it) { auto a = GB->leadMono(it->first); auto b = GB->leadMono(it->second); if (monoid().relativelyPrime(a, b)) { ++stats_relativelyPrimeEliminated; // todo: what are the correct ownership relations here? auto ptr = sig.release(); Hsyz->insert(*ptr); SP->setKnownSyzygies(mSpairTmp); MATHICGB_LOG(SigSPairFinal) << " eliminated by relatively prime criterion.\n"; return true; } } } #ifdef DEBUG for (auto it = mSpairTmp.begin(); it != mSpairTmp.end(); ++it) { auto a = GB->leadMono(it->first); auto b = GB->leadMono(it->second); MATHICGB_ASSERT(!monoid().relativelyPrime(a, b)); } #endif // Reduce the pair ++stats_pairsReduced; if (!processSPair(std::move(sig), mSpairTmp) || !mPostponeKoszul) return true; for (auto it = mSpairTmp.begin(); it != mSpairTmp.end(); ++it) { std::pair p = *it; if (GB->ratioCompare(p.first, p.second) == LT) std::swap(p.first, p.second); auto greaterSig = GB->signature(p.first); auto smallerLead = GB->leadMono(p.second); monomial koszul = R->allocMonomial(); monoid().multiply(greaterSig, smallerLead, koszul); if (Hsyz->member(koszul)) R->freeMonomial(koszul); else mKoszuls.push(koszul); } return true; } size_t SignatureGB::getMemoryUse() const { return GB->getMemoryUse() + Hsyz->getMemoryUse() + R->getMemoryUse() + reducer->getMemoryUse() + mSpairTmp.capacity() * sizeof(mSpairTmp.front()) + SP->getMemoryUse() + mKoszuls.getMemoryUse(); } void SignatureGB::displayStats(std::ostream &o) const { o << "-- stats: -- \n"; o << " strategy: signature" << (mPostponeKoszul ? "-postpone" : "") << (mUseBaseDivisors ? "-basediv" : "") << '\n'; o << " reduction type: " << reducer->description() << '\n'; o << " divisor tab type: " << GB->basis().monoLookup().getName() << '\n'; o << " syzygy tab type: " << Hsyz->name() << '\n'; o << " S-pair queue type: " << SP->name() << '\n'; o << " total compute time: " << stats_nsecs << " -- seconds" << '\n'; displayMemoryUse(o); displaySomeStats(o); o << std::flush; } void SignatureGB::displayPaperStats(std::ostream& out) const { SigSPairs::Stats stats = SP->getStats(); //Reducer::Stats reducerStats = reducer->sigStats(); mic::ColumnPrinter pr; pr.addColumn(true, " "); pr.addColumn(false, " "); pr.addColumn(true, " "); std::ostream& name = pr[0]; std::ostream& value = pr[1]; std::ostream& extra = pr[2]; const unsigned long long considered0 = GB->size() * (GB->size() - 1) / 2; const unsigned long long considered = stats.spairsConstructed; if (considered0 != considered) { name << "WARNING!!! #spairsConstructed is not correct!!\n"; value << '\n'; extra << '\n'; } name << "S-pairs considered:\n"; value << mic::ColumnPrinter::commafy(considered) << '\n'; extra << '\n'; name << "Removed via non-regular criterion:\n"; value << mic::ColumnPrinter::commafy(stats.nonregularSPairs) << '\n'; extra << '\n'; name << "Removed via low base divisor:\n"; value << mic::ColumnPrinter::commafy(stats.lowBaseDivisorHits) << '\n'; extra << '\n'; name << "Removed via high base divisor:\n"; value << mic::ColumnPrinter::commafy(stats.highBaseDivisorHits) << '\n'; extra << '\n'; name << "Removed via signature criterion:\n"; value << mic::ColumnPrinter::commafy(stats.syzygyModuleHits) << '\n'; extra << '\n'; name << "Removed via relatively prime criterion:\n"; value << mic::ColumnPrinter::commafy(stats.earlyRelativelyPrimePairs) << '\n'; extra << '\n'; name << "Removed via singular criterion (early):\n"; value << mic::ColumnPrinter::commafy(stats.earlySingularCriterionPairs) << '\n'; extra << '\n'; name << "Number of queued pairs:\n"; value << mic::ColumnPrinter::commafy(stats.queuedPairs) << '\n'; extra << '\n'; name << "Removed via duplicate signature:\n"; value << mic::ColumnPrinter::commafy(stats.duplicateSignatures) << '\n'; extra << '\n'; name << "Removed via signature criterion (late):\n"; value << mic::ColumnPrinter::commafy(stats_SignatureCriterionLate) << '\n'; extra << '\n'; name << "Removed via Koszul criterion (late):\n"; value << mic::ColumnPrinter::commafy(stats_koszulEliminated) << '\n'; extra << '\n'; name << "Removed via relatively prime criterion (late):\n"; value << mic::ColumnPrinter::commafy(stats_relativelyPrimeEliminated) << '\n'; extra << '\n'; /*name << "Removed (singular reduction):\n"; value << mic::ColumnPrinter::commafy(reducerStats.singularReductions) << '\n'; extra << '\n';*/ //unsigned long long nonzeroReductions = stats_pairsReduced - reducerStats.singularReductions - reducerStats.zeroReductions; /*name << "Number of pairs reduced to signature GB elems:\n"; value << mic::ColumnPrinter::commafy(nonzeroReductions) << '\n'; extra << '\n';*/ /*name << "Number of pairs reduced to new syzygy signatures:\n"; value << mic::ColumnPrinter::commafy(reducerStats.zeroReductions) << '\n'; extra << '\n';*/ /* unsigned long long nleft = considered - stats.nonregularSPairs - stats.lowBaseDivisorHits - stats.highBaseDivisorHits - stats.syzygyModuleHits - stats.earlyRelativelyPrimePairs - stats.earlySingularCriterionPairs; if (nleft != stats.queuedPairs) { name << "WARNING!!! queuedPairs is not correct!!\n"; value << '\n'; extra << '\n'; } nleft = nleft - stats.duplicateSignatures - stats_SignatureCriterionLate - stats_koszulEliminated - stats_relativelyPrimeEliminated - reducerStats.singularReductions - reducerStats.zeroReductions - nonzeroReductions; name << "Number of spairs unaccounted for:\n"; value << mic::ColumnPrinter::commafy(nleft) << '\n'; extra << '\n';*/ #ifdef MATHIC_TRACK_DIV_MASK_HIT_RATIO name << "Divisor Mask Stats" << '\n'; value << '\n'; extra << '\n'; name << " DivMasks Computed: " << '\n'; value << mic::ColumnPrinter::commafy(mathic::DivMaskStats::maskComputes) << '\n'; extra << '\n'; name << " DivMask checks: " << '\n'; value << mic::ColumnPrinter::commafy(mathic::DivMaskStats::maskChecks) << '\n'; extra << '\n'; name << " DivMask hits: " << '\n'; value << mic::ColumnPrinter::commafy(mathic::DivMaskStats::maskHits) << '\n'; extra << '\n'; name << " DivMask divisor checks: " << '\n'; value << mic::ColumnPrinter::commafy(mathic::DivMaskStats::divChecks) << '\n'; extra << '\n'; name << " DivMask divisor divides: " << '\n'; value << mic::ColumnPrinter::commafy(mathic::DivMaskStats::divDivides) << '\n'; extra << '\n'; name << " DivMask divisor hits: " << '\n'; value << mic::ColumnPrinter::commafy(mathic::DivMaskStats::divHits) << '\n'; extra << '\n'; #endif out << "*** Statistics for ISSAC 2012 Paper ***\n" << pr << std::flush; } void SignatureGB::displaySomeStats(std::ostream& out) const { mic::ColumnPrinter pr; pr.addColumn(true, " "); pr.addColumn(false, " "); pr.addColumn(true, " "); std::ostream& name = pr[0]; std::ostream& value = pr[1]; std::ostream& extra = pr[2]; const size_t basisSize = GB->size(); const double mseconds = mTimer.getMilliseconds(); const size_t pending = SP->pairCount(); name << "Time spent:\n"; value << mTimer << '\n'; extra << mic::ColumnPrinter::oneDecimal(mseconds / basisSize) << " ms per basis element\n"; const double pendingRatio = static_cast(pending) / basisSize; name << "Basis elements:\n"; value << mic::ColumnPrinter::commafy(basisSize) << '\n'; extra << mic::ColumnPrinter::oneDecimal(pendingRatio) << " Sp pend per basis ele\n"; const size_t basisTermCount = GB->basis().monomialCount(); name << "Terms for basis:\n"; value << mic::ColumnPrinter::commafy(basisTermCount) << '\n'; extra << mic::ColumnPrinter::ratioInteger(basisTermCount, basisSize) << " terms per basis ele\n"; const size_t minLeadCount = GB->basis().minimalLeadCount(); name << "Minimum lead terms:\n"; value << mic::ColumnPrinter::commafy(minLeadCount) << '\n'; extra << mic::ColumnPrinter::percentInteger(minLeadCount, basisSize) << " basis ele have min lead\n"; const size_t lastMinLead = GB->basis().maxIndexMinimalLead() + 1; const size_t timeSinceLastMinLead = basisSize - lastMinLead; name << "Index of last min lead:\n"; value << mic::ColumnPrinter::commafy(lastMinLead) << '\n'; extra << mic::ColumnPrinter::percentInteger(timeSinceLastMinLead, basisSize) << " of basis added since then\n"; const size_t minSyz = Hsyz->elementCount(); const double syzBasisRatio = static_cast(minSyz) / basisSize; name << "Minimal syzygies:\n"; value << mic::ColumnPrinter::commafy(minSyz) << '\n'; extra << mic::ColumnPrinter::oneDecimal(syzBasisRatio) << " syzygies per basis element\n"; const size_t queuedKoszuls = mKoszuls.size(); const double quedRatio = static_cast(queuedKoszuls) / minSyz; name << "Queued Koszul syzygies:\n"; value << mic::ColumnPrinter::commafy(queuedKoszuls) << '\n'; extra << mic::ColumnPrinter::oneDecimal(quedRatio) << " queued koszuls per msyzygy\n"; const unsigned long long considered = GB->size() * (GB->size() - 1) / 2; name << "S-pairs considered:\n"; value << mic::ColumnPrinter::commafy(considered) << '\n'; extra << '\n'; unsigned long long earlyNonElim; SigSPairs::Stats stats = SP->getStats(); const unsigned long long lowElim = stats.lowBaseDivisorHits; const unsigned long long highElim = stats.highBaseDivisorHits; const unsigned long long syzElim = stats.syzygyModuleHits; earlyNonElim = considered - lowElim - highElim - syzElim; name << "S-pairs not early elim:\n"; value << mic::ColumnPrinter::commafy(earlyNonElim) << '\n'; extra << mic::ColumnPrinter::percentInteger(earlyNonElim, considered) << " of considered\n"; name << "Syz module S-pair elim:\n"; value << mic::ColumnPrinter::commafy(syzElim) << '\n'; extra << mic::ColumnPrinter::percentInteger(syzElim, considered) << " of considered\n"; name << "Low bdiv S-pair elim:\n"; value << mic::ColumnPrinter::commafy(lowElim) << '\n'; extra << mic::ColumnPrinter::percentInteger(lowElim, considered) << " of considered\n"; name << "High bdiv S-pair elim:\n"; value << mic::ColumnPrinter::commafy(highElim) << '\n'; extra << mic::ColumnPrinter::percentInteger(highElim, considered) << " of considered\n"; const unsigned long long hadLow = stats.hasLowBaseDivisor; name << "Basis ele had low bdiv:\n"; value << mic::ColumnPrinter::commafy(hadLow) << '\n'; extra << mic::ColumnPrinter::percentInteger(hadLow, basisSize) << " of basis ele\n"; const unsigned long long hadHigh = stats.hasHighBaseDivisor; name << "Basis ele had high bdiv:\n"; value << mic::ColumnPrinter::commafy(hadHigh) << '\n'; extra << mic::ColumnPrinter::percentInteger(hadHigh, basisSize) << " of basis ele\n"; name << "S-pairs pending:\n"; value << mic::ColumnPrinter::commafy(pending) << '\n'; extra << mic::ColumnPrinter::percentInteger(pending, considered) << " of considered\n"; const size_t done = stats_sPairsDone; name << "S pairs done:\n"; value << mic::ColumnPrinter::commafy(done) << '\n'; extra << mic::ColumnPrinter::percentInteger(done, earlyNonElim) << " of not early elim\n"; const size_t sigsDone = stats_sPairSignaturesDone; const double perSig = static_cast(done) / sigsDone; name << "S pair sigs done:\n"; value << mic::ColumnPrinter::commafy(sigsDone) << '\n'; extra << mic::ColumnPrinter::oneDecimal(perSig) << " spairs per signature\n"; //Reducer::Stats reducerStats = reducer->sigStats(); /*const unsigned long long reductions = reducerStats.reductions; const size_t koszulElim = stats_koszulEliminated; name << "Koszul sp eliminated:\n"; value << mic::ColumnPrinter::commafy(koszulElim) << '\n'; extra << mic::ColumnPrinter::percentInteger(koszulElim, sigsDone - reductions) << " of late eliminations\n";*/ /*const size_t primeElim = stats_relativelyPrimeEliminated; name << "Rel.prime sp eliminated:\n"; value << mic::ColumnPrinter::commafy(primeElim) << '\n'; extra << mic::ColumnPrinter::percentInteger(primeElim, sigsDone - reductions) << " of late eliminations\n";*/ /*name << "Signature reductions:\n"; value << mic::ColumnPrinter::commafy(reductions) << '\n'; extra << mic::ColumnPrinter::percentInteger(reductions, sigsDone) << " of S-pairs are reduced\n";*/ /*const unsigned long long singularReductions = reducerStats.singularReductions; name << "Singular reductions:\n"; value << mic::ColumnPrinter::commafy(singularReductions) << '\n'; extra << mic::ColumnPrinter::percentInteger(singularReductions, reductions) << " of reductions\n";*/ /*const unsigned long long zeroReductions = reducerStats.zeroReductions; name << "Reductions to zero:\n"; value << mic::ColumnPrinter::commafy(zeroReductions) << '\n'; extra << mic::ColumnPrinter::percentInteger(zeroReductions, reductions) << " of reductions\n";*/ /*const unsigned long long newReductions = reductions - singularReductions - zeroReductions; name << "Reductions to new ele:\n"; value << mic::ColumnPrinter::commafy(newReductions) << '\n'; extra << mic::ColumnPrinter::percentInteger(newReductions, reductions) << " of reductions\n";*/ /*const unsigned long long redSteps = reducerStats.steps; const double stepsRatio = static_cast(redSteps) / (reductions - singularReductions); name << "Sig reduction steps:\n"; value << mic::ColumnPrinter::commafy(redSteps) << '\n'; extra << mic::ColumnPrinter::oneDecimal(stepsRatio) << " steps per non-sing reduction\n";*/ /*const unsigned long long longestReduction = reducerStats.maxSteps; name << "Longest sig reduction:\n"; value << mic::ColumnPrinter::commafy(longestReduction) << '\n'; extra << '\n';*/ /*Reducer::Stats classicRedStats = reducer->classicStats(); const unsigned long long clReductions = classicRedStats.reductions; name << "Classic reductions:\n"; value << mic::ColumnPrinter::commafy(clReductions) << '\n'; extra << '\n';*/ /*const unsigned long long clRedSteps = classicRedStats.steps; const double clStepsRatio = static_cast(clRedSteps) / clReductions; name << "Classic reduction steps:\n"; value << mic::ColumnPrinter::commafy(clRedSteps) << '\n'; extra << mic::ColumnPrinter::oneDecimal(clStepsRatio) << " steps per reduction\n";*/ /*const unsigned long long clLongestReduction = classicRedStats.maxSteps; name << "Longest classic red:\n"; value << mic::ColumnPrinter::commafy(clLongestReduction) << '\n'; extra << '\n';*/ out << "*** Some of the statistics ***\n" << pr << std::flush; } void SignatureGB::displayMemoryUse(std::ostream& out) const { // set up printer mic::ColumnPrinter pr; pr.addColumn(); pr.addColumn(false); pr.addColumn(false); std::ostream& name = pr[0]; std::ostream& value = pr[1]; std::ostream& extra = pr[2]; const size_t total = getMemoryUse(); { // Grobner basis const size_t basisMem = GB->getMemoryUse(); name << "Grobner basis:\n"; value << mic::ColumnPrinter::bytesInUnit(basisMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(basisMem, total) << '\n'; } { // Spairs const size_t sPairMem = SP->getMemoryUse(); name << "S-pairs:\n"; value << mic::ColumnPrinter::bytesInUnit(sPairMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(sPairMem, total) << '\n'; const size_t knownSyzygyMem = SP->getKnownSyzygyBitsMemoryUse(); name << " Known syzygy bits:\n"; value << mic::ColumnPrinter::bytesInUnit(knownSyzygyMem) << '\n'; extra << '\n'; } { // Syzygies const size_t syzMem = Hsyz->getMemoryUse(); name << "Minimal syzygies:\n"; value << mic::ColumnPrinter::bytesInUnit(syzMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(syzMem, total) << '\n'; } { // Koszul queue const size_t syzQueueMem = mKoszuls.getMemoryUse(); name << "Koszul queue:\n"; value << mic::ColumnPrinter::bytesInUnit(syzQueueMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(syzQueueMem, total) << '\n'; } { // Reducer const size_t reducerMem = reducer->getMemoryUse(); name << "Reducer:\n"; value << mic::ColumnPrinter::bytesInUnit(reducerMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(reducerMem, total) << '\n'; } { // Signatures const size_t sigMem = R->getMemoryUse(); name << "Signatures:\n"; value << mic::ColumnPrinter::bytesInUnit(sigMem) << '\n'; extra << mic::ColumnPrinter::percentInteger(sigMem, total) << '\n'; } // total name << "-------------\n"; value << '\n'; extra << '\n'; name << "Memory used in total:\n"; value << mic::ColumnPrinter::bytesInUnit(total) << "\n"; extra << "\n"; out << "*** Summary of memory use ***\n" << pr << std::flush; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/SignatureGB.hpp000077500000000000000000000056261311555162500213750ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SIGNATURE_G_B_GUARD #define MATHICGB_SIGNATURE_G_B_GUARD #include "PolyRing.hpp" #include "ModuleMonoSet.hpp" #include "SigPolyBasis.hpp" #include "SigSPairs.hpp" #include "Reducer.hpp" #include "KoszulQueue.hpp" #include "SPairs.hpp" #include "MonoProcessor.hpp" #include MATHICGB_NAMESPACE_BEGIN class SigSPairs; class SignatureGB { public: typedef PolyRing::Monoid Monoid; typedef Monoid::Mono Mono; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef Monoid::MonoVector MonoVector; typedef MonoProcessor Processor; typedef Monoid::Component Component; SignatureGB( Basis&& basis, Processor&& processor, Reducer::ReducerType reductiontyp, int divlookup_type, int montable_type, bool postponeKoszul, bool useBaseDivisors, bool preferSparseReducers, bool useSingularCriterionEarly, size_t queueType); void computeGrobnerBasis(); SigPolyBasis* getGB() { return GB.get(); } ModuleMonoSet* getSyzTable() { return mProcessor->processingNeeded() ? Hsyz2.get() : Hsyz.get(); } SigSPairs* getSigSPairs() { return SP.get(); } size_t getMemoryUse() const; void displayStats(std::ostream& out) const; void displayPaperStats(std::ostream& out) const; void displayMemoryUse(std::ostream& out) const; void displaySomeStats(std::ostream& out) const; void setBreakAfter(unsigned int elements) { mBreakAfter = elements; } void setPrintInterval(unsigned int reductions) { mPrintInterval = reductions; } const Monoid& monoid() const {return R->monoid();} private: unsigned int mBreakAfter; unsigned int mPrintInterval; bool processSPair(Mono sig, const SigSPairs::PairContainer& pairs); bool step(); const PolyRing *R; bool const mPostponeKoszul; // Currently we use either both criteria (high and loow) or neither. bool const mUseBaseDivisors; SigSPairs::PairContainer mSpairTmp; // use only for getting S-pairs // stats ////////// size_t stats_sPairSignaturesDone; // distinct S-pair signatures done size_t stats_sPairsDone; // total S-pairs done size_t stats_koszulEliminated; // S-pairs eliminated due to Koszul queue size_t stats_SignatureCriterionLate; // # spairs removed due to being a syz signature // S-pairs eliminated due to relatively prime criterion size_t stats_relativelyPrimeEliminated; size_t stats_pairsReduced; // # spairs actually sent for reduction mic::Timer mTimer; double stats_nsecs; std::unique_ptr GB; KoszulQueue mKoszuls; std::unique_ptr Hsyz; std::unique_ptr Hsyz2; std::unique_ptr reducer; std::unique_ptr SP; std::unique_ptr> mProcessor; }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/SparseMatrix.cpp000077500000000000000000000435761311555162500216460ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "SparseMatrix.hpp" #include "Poly.hpp" #include MATHICGB_NAMESPACE_BEGIN void SparseMatrix::takeRowsFrom(SparseMatrix&& matrix) { if (matrix.mRows.empty()) return; if (mRows.empty()) { *this = std::move(matrix); return; } Block* oldestBlock = &matrix.mBlock; while (oldestBlock->mPreviousBlock != 0) oldestBlock = oldestBlock->mPreviousBlock; if (mBlock.mHasNoRows) // only put mBlock in chain of blocks if non-empty oldestBlock->mPreviousBlock = mBlock.mPreviousBlock; else oldestBlock->mPreviousBlock = new Block(std::move(mBlock)); mBlock = std::move(matrix.mBlock); mRows.insert(mRows.end(), matrix.mRows.begin(), matrix.mRows.end()); matrix.clear(); } void SparseMatrix::rowToPolynomial( const RowIndex row, const std::vector& colMonomials, Poly& poly ) { poly.setToZero(); poly.reserve(entryCountInRow(row)); const auto end = rowEnd(row); for (auto it = rowBegin(row); it != end; ++it) { MATHICGB_ASSERT(it.index() < colMonomials.size()); if (it.scalar() != 0) poly.append(it.scalar(), *colMonomials[it.index()]); } MATHICGB_ASSERT(poly.termsAreInDescendingOrder()); } void SparseMatrix::sortRowsByIncreasingPivots() { SparseMatrix ordered; const auto rowCount = this->rowCount(); std::vector rows(rowCount); for (RowIndex row = 0; row < rowCount; ++row) rows[row] = row; const auto lexLess = [&](const RowIndex a, const RowIndex b) -> bool { auto aIt = rowBegin(a); auto bIt = rowBegin(b); const auto aEnd = rowEnd(a); const auto bEnd = rowEnd(b); for (; aIt != aEnd && bIt != bEnd; ++aIt, ++bIt) { if (*aIt < *bIt) return true; if (*aIt > *bIt) return false; ++aIt; ++bIt; } return aIt == aEnd && bIt != bEnd; }; std::sort(rows.begin(), rows.end(), lexLess); // construct ordered with pivot columns in increasing order ordered.clear(); for (size_t i = 0; i < rowCount; ++i) ordered.appendRow(*this, rows[i]); *this = std::move(ordered); } void SparseMatrix::applyColumnMap(const std::vector& colMap) { MATHICGB_ASSERT(colMap.size() >= computeColCount()); Block* block = &mBlock; for (; block != 0; block = block->mPreviousBlock) { const auto end = block->mColIndices.end(); for (auto it = block->mColIndices.begin(); it != end; ++it) *it = colMap[*it]; } } void SparseMatrix::multiplyRow( const RowIndex row, const Scalar multiplier, const Scalar modulus ) { MATHICGB_ASSERT(row < rowCount()); const auto end = rowEnd(row); for (auto it = rowBegin(row); it != end; ++it) it.setScalar(modularProduct(it.scalar(), multiplier, modulus)); } void SparseMatrix::print(std::ostream& out) const { if (rowCount() == 0) out << "matrix with no rows\n"; for (RowIndex row = 0; row < rowCount(); ++row) { out << row << ':'; const auto end = rowEnd(row); for (auto it = rowBegin(row); it != end; ++it) out << ' ' << it.index() << '#' << it.scalar(); out << '\n'; } } void SparseMatrix::printStatistics(std::ostream& out) const { typedef mathic::ColumnPrinter ColPr; ColPr pr; pr.addColumn(false, " ", ""); pr.addColumn(false, "", ""); pr.addColumn(true, "", ""); const auto memory = memoryUse(); const auto colCount = computeColCount(); const auto entryCount = this->entryCount(); const uint64 area = static_cast(rowCount()) * static_cast(colCount); pr[0] << "\n/\n" << ColPr::commafy(rowCount()) << " |\nrows |\n\\\n"; const char* const line = "------------------\n"; pr[1] << ColPr::commafy(colCount) << " \n" << line << ColPr::withSIPrefix(entryCount) << " -" << ColPr::percentIntegerFixed(entryCount, area) << " \n" << ColPr::bytesInUnit(memory) << " -" << ColPr::percentIntegerFixed(memoryUseTrimmed(), memory) << " \n" << line; pr[2] << " columns\n\\\n| non-zero (density)\n| memory (used)\n/\n"; out << '\n' << pr << "\n"; } std::string SparseMatrix::toString() const { std::ostringstream out; print(out); return out.str(); } void SparseMatrix::appendRowAndNormalize( const SparseMatrix& matrix, const RowIndex row, const Scalar modulus ) { MATHICGB_ASSERT(row < matrix.rowCount()); auto it = matrix.rowBegin(row); const auto end = matrix.rowEnd(row); if (it != end) { appendEntry(it.index(), 1); const Scalar lead = it.scalar(); ++it; if (it != end) { const Scalar inverse = modularInverse(lead, modulus); do { const uint32 prod = static_cast(inverse) * it.scalar(); const uint16 prodMod = static_cast(prod % modulus); appendEntry(it.index(), prodMod); ++it; } while (it != end); } } rowDone(); } void SparseMatrix::appendRow(const SparseMatrix& matrix, const RowIndex row) { MATHICGB_ASSERT(row < matrix.rowCount()); const auto size = matrix.entryCountInRow(row); while (mBlock.mScalars.capacityToGo() < size) growEntryCapacity(); MATHICGB_ASSERT(mBlock.mScalars.capacityToGo() == mBlock.mColIndices.capacityToGo()); auto const data = matrix.mRows[row]; mBlock.mScalars.memcpy(data.mScalarsBegin, size); mBlock.mColIndices.memcpy(data.mIndicesBegin, size); rowDone(); } SparseMatrix& SparseMatrix::operator=(const SparseMatrix& matrix) { // todo: use copy-swap or copy-move. clear(); mMemoryQuantum = matrix.mMemoryQuantum; // A version that works on each block would be faster, but this is not // used anywhere time-critical right now. Improve this if it turns // up in profiling at some point. for (RowIndex row = 0; row < matrix.rowCount(); ++row) appendRow(matrix, row); return *this; } void SparseMatrix::swap(SparseMatrix& matrix) { mBlock.swap(matrix.mBlock); using std::swap; swap(mRows, matrix.mRows); swap(mMemoryQuantum, matrix.mMemoryQuantum); } bool SparseMatrix::operator==(const SparseMatrix& matrix) const { const auto count = rowCount(); if (count != matrix.rowCount()) return false; for (RowIndex row = 0; row < count; ++row) { if (entryCountInRow(row) != matrix.entryCountInRow(row)) return false; const auto end = rowEnd(row); auto it = rowBegin(row); auto matrixIt = matrix.rowBegin(row); for (auto it = rowBegin(row); it != end; ++it, ++matrixIt) if (*it != *matrixIt) return false; } return true; } SparseMatrix::ColIndex SparseMatrix::computeColCount() const { // Obviously this can be done faster, but there has not been a need for that // so far. ColIndex colCount = 0; for (RowIndex row = 0; row < rowCount(); ++row) { const auto end = rowEnd(row); for (auto it = rowBegin(row); it != end; ++it) colCount = std::max(colCount, it.index() + 1); } return colCount; } void SparseMatrix::clear() { Block* block = &mBlock; while (block != 0) { delete[] block->mColIndices.releaseMemory(); delete[] block->mScalars.releaseMemory(); Block* const tmp = block->mPreviousBlock; if (block != &mBlock) delete block; block = tmp; } mBlock.mPreviousBlock = 0; mBlock.mHasNoRows = true; mRows.clear(); } void SparseMatrix::appendRowWithModulus( std::vector const& v, const Scalar modulus ) { const auto count = static_cast(v.size()); for (ColIndex col = 0; col < count; ++col) { const Scalar scalar = static_cast(v[col] % modulus); if (scalar != 0) appendEntry(col, scalar); } rowDone(); } void SparseMatrix::appendRowWithModulusNormalized( std::vector const& v, const Scalar modulus ) { uint16 multiply = 1; bool first = true; const auto count = static_cast(v.size()); for (ColIndex col = 0; col < count; ++col) { Scalar scalar = static_cast(v[col] % modulus); if (scalar == 0) continue; if (first) { multiply = modularInverse(scalar, modulus); scalar = 1; first = false; } else { uint32 prod = static_cast(multiply) * scalar; scalar = prod % modulus; } appendEntry(col, scalar); } rowDone(); } bool SparseMatrix::appendRowWithModulusIfNonZero( std::vector const& v, const Scalar modulus ) { appendRowWithModulus(v, modulus); MATHICGB_ASSERT(rowCount() > 0); if (mRows.back().empty()) { mRows.pop_back(); return false; } else return true; } void SparseMatrix::trimLeadingZeroColumns(const ColIndex trimThisMany) { Block* block = &mBlock; for (; block != 0; block = block->mPreviousBlock) { const auto end = block->mColIndices.end(); for (auto it = block->mColIndices.begin(); it != end; ++it) { MATHICGB_ASSERT(*it >= trimThisMany); *it -= trimThisMany; } } } void SparseMatrix::reserveFreeEntries(const size_t freeCount) { if (freeCount <= mBlock.mColIndices.capacity() - mBlock.mColIndices.size()) return; // We need to copy over the pending entries, so we need space for those // entries on top of freeCount. const size_t count = freeCount + ( // todo: detect overflow for this addition mBlock.mHasNoRows ? mBlock.mColIndices.size() : std::distance(mRows.back().mIndicesEnd, mBlock.mColIndices.end()) ); // @todo: fix memory leaks on exception auto oldBlock = new Block(std::move(mBlock)); MATHICGB_ASSERT(mBlock.mColIndices.begin() == 0); MATHICGB_ASSERT(mBlock.mScalars.begin() == 0); MATHICGB_ASSERT(mBlock.mHasNoRows); MATHICGB_ASSERT(mBlock.mPreviousBlock == 0); { const auto begin = new ColIndex[count]; const auto capacityEnd = begin + count; mBlock.mColIndices.releaseAndSetMemory(begin, begin, capacityEnd); } { const auto begin = new Scalar[count]; const auto capacityEnd = begin + count; mBlock.mScalars.releaseAndSetMemory(begin, begin, capacityEnd); } // copy pending entries over if (oldBlock->mHasNoRows) { mBlock.mColIndices.rawAssign (oldBlock->mColIndices.begin(), oldBlock->mColIndices.end()); mBlock.mScalars.rawAssign (oldBlock->mScalars.begin(), oldBlock->mScalars.end()); delete oldBlock; // no reason to keep it around } else { mBlock.mColIndices.rawAssign (mRows.back().mIndicesEnd, oldBlock->mColIndices.end()); mBlock.mScalars.rawAssign (mRows.back().mScalarsEnd, oldBlock->mScalars.end()); // remove the pending entries from old block so that counting the number // of entries will give the correct result in future. oldBlock->mColIndices.resize (std::distance(oldBlock->mColIndices.begin(), mRows.back().mIndicesEnd)); oldBlock->mScalars.resize (std::distance(oldBlock->mScalars.begin(), mRows.back().mScalarsEnd)); mBlock.mPreviousBlock = oldBlock; } } void SparseMatrix::growEntryCapacity() { MATHICGB_ASSERT(mBlock.mColIndices.size() == mBlock.mScalars.size()); MATHICGB_ASSERT(mBlock.mColIndices.capacity() == mBlock.mScalars.capacity()); MATHICGB_ASSERT(mBlock.mColIndices.size() <= mBlock.mColIndices.capacity()); // TODO: handle overflow of arithmetic here if (mMemoryQuantum != 0 && (!mBlock.mHasNoRows || mBlock.mPreviousBlock == 0) ) reserveFreeEntries(mMemoryQuantum); else if (mBlock.mColIndices.capacity() == 0) reserveFreeEntries(1 << 14); // minimum block size else { // do this if the quantum is not set or if the quantum is too small // to store a single row being built. reserveFreeEntries(mBlock.mColIndices.capacity() * 2); } MATHICGB_ASSERT(mBlock.mColIndices.size() <= mBlock.mColIndices.capacity()); MATHICGB_ASSERT(mBlock.mColIndices.size() == mBlock.mScalars.size()); } float SparseMatrix::computeDensity() const { const auto rowCount = static_cast(this->rowCount()); const auto colCount = static_cast(computeColCount()); const auto entryCount = static_cast(this->entryCount()); return entryCount / (rowCount * colCount); } size_t SparseMatrix::entryCount() const { size_t count = 0; const Block* block = &mBlock; for (; block != 0; block = block->mPreviousBlock) count += block->mColIndices.size(); return count; } size_t SparseMatrix::memoryUse() const { size_t count = 0; for (auto block = &mBlock; block != 0; block = block->mPreviousBlock) count += block->memoryUse() + sizeof(Block); return count; } size_t SparseMatrix::memoryUseTrimmed() const { size_t count = 0; for (auto block = &mBlock; block != 0; block = block->mPreviousBlock) count += block->memoryUseTrimmed() + sizeof(Block); return count; } size_t SparseMatrix::Block::memoryUse() const { return mColIndices.memoryUse() + mScalars.memoryUse(); } size_t SparseMatrix::Block::memoryUseTrimmed() const { return mColIndices.memoryUseTrimmed() + mScalars.memoryUseTrimmed(); } std::ostream& operator<<(std::ostream& out, const SparseMatrix& matrix) { matrix.print(out); return out; } namespace { template T readOne(FILE* file) { T t; if (fread(&t, sizeof(T), 1, file) != 1) mathic::reportError("error while reading file."); return t; } template void writeOne(const T& t, FILE* file) { if (fwrite(&t, sizeof(T), 1, file) != 1) mathic::reportError("error while writing to file."); } template void writeMany(const std::vector& v, FILE* file) { if (v.empty()) return; if (fwrite(v.data(), sizeof(T), v.size(), file) != v.size()) mathic::reportError("error while writing to file."); } template void readMany(FILE* file, size_t count, std::vector& v) { size_t const originalSize = v.size(); v.resize(originalSize + count); if (fread(v.data() + originalSize, sizeof(T), count, file) != count) mathic::reportError("error while reading file."); } } void SparseMatrix::write(const Scalar modulus, FILE* file) const { const auto storedRowCount = rowCount(); writeOne(static_cast(storedRowCount), file); writeOne(static_cast(computeColCount()), file); writeOne(static_cast(modulus), file); writeOne(static_cast(entryCount()), file); // write scalars for (SparseMatrix::RowIndex row = 0; row < storedRowCount; ++row) { const auto count = entryCountInRow(row); if (fwrite(&rowBegin(row).scalar(), sizeof(uint16), count, file) != count) mathic::reportError("error while writing to file."); } // write indices for (SparseMatrix::RowIndex row = 0; row < storedRowCount; ++row) { const auto count = entryCountInRow(row); if (fwrite(&rowBegin(row).index(), sizeof(uint32), count, file) != count) mathic::reportError("error while writing to file."); } std::vector entryCounts; for (SparseMatrix::RowIndex row = 0; row < storedRowCount; ++row) entryCounts.push_back(entryCountInRow(row)); writeMany(entryCounts, file); } SparseMatrix::Scalar SparseMatrix::read(FILE* file) { MATHICGB_ASSERT(file != 0); const auto rowCount = readOne(file); const auto colCount = readOne(file); const auto modulus = readOne(file); const auto entryCount64 = readOne(file); if (entryCount64 > std::numeric_limits::max()) throw std::bad_alloc(); const auto entryCount = static_cast(entryCount64); // Allocate memory to hold the matrix in one block. clear(); reserveFreeEntries(entryCount); mRows.reserve(rowCount); MATHICGB_ASSERT(mBlock.mPreviousBlock == 0); // only one block // @todo: we can read directly into the block. Do that. // Read scalars. { mBlock.mScalars.resize(entryCount); std::vector scalars; readMany(file, entryCount, scalars); std::copy(scalars.begin(), scalars.end(), mBlock.mScalars.begin()); } // Read column indices. { mBlock.mColIndices.resize(entryCount); std::vector indices; readMany(file, entryCount, indices); std::copy(indices.begin(), indices.end(), mBlock.mColIndices.begin()); } // Read where rows begin and end. { std::vector sizes; readMany(file, rowCount, sizes); uint32 runningOffset = 0; for (auto it = sizes.begin(); it != sizes.end(); ++it) { Row row; row.mIndicesBegin = mBlock.mColIndices.begin() + runningOffset; row.mScalarsBegin = mBlock.mScalars.begin() + runningOffset; runningOffset += *it; row.mIndicesEnd = mBlock.mColIndices.begin() + runningOffset; row.mScalarsEnd = mBlock.mScalars.begin() + runningOffset; mRows.push_back(row); } MATHICGB_ASSERT(runningOffset == entryCount); } MATHICGB_ASSERT(mBlock.mPreviousBlock == 0); // still only one block return modulus; } void SparseMatrix::writePBM(FILE* file) { // See http://netpbm.sourceforge.net/doc/pbm.html const auto rowCount = this->rowCount(); auto colCount = this->computeColCount(); colCount += 8-(colCount % 8); // Write PBM header { std::stringstream out; out << "P1 " << colCount << ' ' << rowCount << '\n'; fputs(out.str().c_str(), file); } for (RowIndex row = 0; row < rowCount; ++row) { const auto end = rowEnd(row); auto it = rowBegin(row); unsigned char byte = 0; unsigned int bit = (1 << 8); for (ColIndex col = 0; col < colCount; ++col) { if (it != end && col == it.index()) { fputc('1', file); byte |= bit; ++it; } else fputc('0', file); bit >>= 1; if (bit == 0) { // fputc(byte, file); byte = 0; bit = (1 << 8); } } fputc('\n', file); // if (bit != (1 << 8)) // fputc(byte, file); } } bool SparseMatrix::debugAssertValid() const { for (RowIndex row = 0; row < rowCount(); ++row) { for (auto it = rowBegin(row); it != rowEnd(row); ++it) { // A scalar of 0 is not necessarily bad, it is just not expected // at the time of writing this assert. Feel free to remove this assert // if you are creating scalars that are zero on purpose. MATHICGB_ASSERT(it.scalar() != 0); } } return true; } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/SparseMatrix.hpp000077500000000000000000000350241311555162500216400ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_SPARSE_MATRIX_GUARD #define MATHICGB_SPARSE_MATRIX_GUARD #include "RawVector.hpp" #include "PolyRing.hpp" #include #include #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN class Poly; /** A class that implements a sparse matrix. These are the mathematical concepts involved: Sparse matrix: a sequence of sparse rows. Sparse row: a seqence of entries. Entry: a pair (i,s) where i is a column index and s is a scalar. You add a row by adding all entries in the row and then calling rowDone(). You cannot add entries to a row once it has been created, so in that sense this class is append-only. However, you are free to change the indices and the scalars in the entries that are already there. Entries are not automatically reordered by this class, so your rows will be in increasing order of index only if you make them like that. Adding an entry or a row can invalidate all pointers/references to entries in the matrix and all iterators. This is true even if the entry has been added but it has not been put in a new row yet by calling rowDone. There is no special treatment of entries whose scalar is zero. For example they still count as entries in relation to entryCount(). Currently this is not a template class so you can get by without using the typedefs offered, for example using uint16 instead of SparseMatrix::Scalar. Please use the typedefs to make it easier to support a wider range of types of matrices in future. */ class SparseMatrix { public: typedef uint32 RowIndex; typedef uint32 ColIndex; typedef uint16 Scalar; class ConstRowIterator; class RowIterator; /// Construct a matrix with no rows. SparseMatrix(const size_t memoryQuantum = 0): mMemoryQuantum(memoryQuantum) {} SparseMatrix(SparseMatrix&& matrix): mRows(std::move(matrix.mRows)), mBlock(std::move(matrix.mBlock)), mMemoryQuantum(matrix.mMemoryQuantum) { } SparseMatrix& operator=(SparseMatrix&& matrix) { this->~SparseMatrix(); new (this) SparseMatrix(std::move(matrix)); return *this; } SparseMatrix(const SparseMatrix& matrix) { *this = matrix; } ~SparseMatrix() {clear();} SparseMatrix& operator=(const SparseMatrix&); void swap(SparseMatrix& matrix); bool operator==(const SparseMatrix& matrix) const; bool operator!=(const SparseMatrix& matrix) const { return !(*this == matrix); } // Removes all rows from *this. void clear(); /// Appends the rows from matrix to this object. Avoids most of the copies /// that would otherwise be required for a big matrix insert by taking /// the memory out of matrix. void takeRowsFrom(SparseMatrix&& matrix); RowIndex rowCount() const {return static_cast(mRows.size());} ColIndex computeColCount() const; size_t memoryQuantum() const {return mMemoryQuantum;} /// Returns number of non-zero entries divide by the product of the number of /// rows times the number of columns. So it is the proportion of non-zero /// entries. float computeDensity() const; /// Returns the number of entries in the whole matrix. Is not constant time /// so avoid calling too many times. size_t entryCount() const; /// Returns the number of bytes of memory allocated by this object. Is not /// constant time so avoid calling too many times. size_t memoryUse() const; size_t memoryUseTrimmed() const; /// Returns the number of entries in the given row. ColIndex entryCountInRow(RowIndex row) const { MATHICGB_ASSERT(row < rowCount()); return mRows[row].size(); } /// Returns true if the given row has no entries. bool emptyRow(RowIndex row) const { MATHICGB_ASSERT(row < rowCount()); return mRows[row].empty(); } ConstRowIterator rowBegin(RowIndex row) const { MATHICGB_ASSERT(row < rowCount()); const Row& r = mRows[row]; return ConstRowIterator(r.mIndicesBegin, r.mScalarsBegin); } RowIterator rowBegin(RowIndex row) { MATHICGB_ASSERT(row < rowCount()); const Row& r = mRows[row]; return RowIterator(r.mIndicesBegin, r.mScalarsBegin); } ConstRowIterator rowEnd(RowIndex row) const { MATHICGB_ASSERT(row < rowCount()); const Row& r = mRows[row]; return ConstRowIterator(r.mIndicesEnd, r.mScalarsEnd); } RowIterator rowEnd(RowIndex row) { MATHICGB_ASSERT(row < rowCount()); const Row& r = mRows[row]; return RowIterator(r.mIndicesEnd, r.mScalarsEnd); } /// Returns the index of the first entry in the given row. This is /// the first entry that you added to the row - so not necessarily the /// minimum column index in that row. The row in question must have at /// least one entry. ColIndex leadCol(RowIndex row) const { MATHICGB_ASSERT(row < rowCount()); MATHICGB_ASSERT(!emptyRow(row)); return *mRows[row].mIndicesBegin; } /// Prints the matrix in a human readable format to out. /// Useful for debugging. void print(std::ostream& out) const; void printStatistics(std::ostream& out) const; std::string toString() const; /// Removes the leading trimThisMany columns. The columns are /// removed by replacing all column indices col by col - /// trimThisMany. No entry can have a column index less than /// trimThisMany, even if the scalar of that entry is set to zero. void trimLeadingZeroColumns(ColIndex trimThisMany); /// Ensure that there is enough space for at least freeCount additional /// entries without needing to allocate more memory for entries. /// Pending entries that are not fixed into a row yet do not count as /// free for this calculation. void reserveFreeEntries(size_t freeCount); /// Preallocate space for at least count rows. This is separate from the /// space to store the entries in those rows. void reserveRows(size_t count) {mRows.reserve(count);} /// Adds a new row that contains all terms that have been appended /// since the last time a row was added or the matrix was created. void rowDone() { MATHICGB_ASSERT(mBlock.mColIndices.size() == mBlock.mScalars.size()); Row row; row.mIndicesEnd = mBlock.mColIndices.end(); row.mScalarsEnd = mBlock.mScalars.end(); if (mBlock.mHasNoRows) { row.mIndicesBegin = mBlock.mColIndices.begin(); row.mScalarsBegin = mBlock.mScalars.begin(); mBlock.mHasNoRows = false; } else { row.mIndicesBegin = mRows.back().mIndicesEnd; row.mScalarsBegin = mRows.back().mScalarsEnd; } mRows.push_back(row); } /// Appends an entry to the matrix. Will not appear in the matrix /// until rowDone is called. Do not call other methods that add rows /// after calling this method until rowDone has been called. inline void appendEntry(ColIndex colIndex, Scalar scalar) { MATHICGB_ASSERT(mBlock.mColIndices.size() == mBlock.mScalars.size()); MATHICGB_ASSERT(mBlock.mScalars.atCapacity() == mBlock.mColIndices.atCapacity()); if (mBlock.mScalars.atCapacity()) growEntryCapacity(); MATHICGB_ASSERT(!mBlock.mScalars.atCapacity()); MATHICGB_ASSERT(!mBlock.mColIndices.atCapacity()); mBlock.mColIndices.rawPushBack(colIndex); mBlock.mScalars.rawPushBack(scalar); MATHICGB_ASSERT(mBlock.mColIndices.size() == mBlock.mScalars.size()); } void appendRowAndNormalize(const SparseMatrix& matrix, RowIndex row, Scalar modulus); void appendRow(const SparseMatrix& matrix, RowIndex row); void appendRowWithModulus(const std::vector& v, Scalar modulus); template void appendRow(const std::vector& v, ColIndex leadCol = 0); void appendRowWithModulusNormalized(const std::vector& v, Scalar modulus); // Returns true if the row was non-zero. Otherwise the row was not // appended. bool appendRowWithModulusIfNonZero(const std::vector& v, Scalar modulus); /// Replaces all column indices i with colMap[i]. void applyColumnMap(const std::vector& colMap); void multiplyRow(RowIndex row, Scalar multiplier, Scalar modulus); /// Let poly be the dot product of colMonomials and the given row. void rowToPolynomial( RowIndex row, const std::vector& colMonomials, Poly& poly); /// Reorders the rows so that the index of the leading column in /// each row is weakly increasing going from top to bottom. Quite /// slow and it makes a copy internally. void sortRowsByIncreasingPivots(); /// Write *this and modulus to file. void write(Scalar modulus, FILE* file) const; /// Set *this to a matrix read from file and return the modulus from the file. Scalar read(FILE* file); /// Write a 0-1 bitmap in PBM format to file. This is useful for /// debugging as it allows visual inspection of large matrices. void writePBM(FILE* file); /// Iterates through the entries in a row. class ConstRowIterator { public: typedef const std::pair value_type; typedef ptrdiff_t difference_type; typedef size_t distance_type; typedef value_type* pointer; typedef value_type& reference; typedef std::random_access_iterator_tag iterator_category; ConstRowIterator& operator++() { ++mScalarIt; ++mColIndexIt; return *this; } ConstRowIterator& operator+=(difference_type i) { mScalarIt += i; mColIndexIt += i; return *this; } value_type operator*() const {return value_type(index(), scalar());} bool operator<(const ConstRowIterator& it) const { return mColIndexIt < it.mColIndexIt; } difference_type operator-(const ConstRowIterator& it) const { return mColIndexIt - it.mColIndexIt; } bool operator==(const ConstRowIterator& it) const { return mColIndexIt == it.mColIndexIt; } bool operator!=(const ConstRowIterator& it) const {return !(*this == it);} const Scalar& scalar() const {return *mScalarIt;} const ColIndex& index() const {return *mColIndexIt;} private: friend class SparseMatrix; ConstRowIterator( const ColIndex* const indicesIt, const Scalar* const scalarIt ): mColIndexIt(indicesIt), mScalarIt(scalarIt) { } const ColIndex* mColIndexIt; const Scalar* mScalarIt; }; /// Iterates through the entries in a row. class RowIterator { public: typedef const std::pair value_type; typedef ptrdiff_t difference_type; typedef size_t distance_type; typedef value_type* pointer; typedef value_type& reference; typedef std::random_access_iterator_tag iterator_category; RowIterator& operator++() { ++mScalarIt; ++mColIndexIt; return *this; } RowIterator& operator+=(difference_type i) { mScalarIt += i; mColIndexIt += i; return *this; } value_type operator*() const {return value_type(index(), scalar());} bool operator<(const RowIterator& it) const { return mColIndexIt < it.mColIndexIt; } difference_type operator-(const RowIterator& it) const { return mColIndexIt - it.mColIndexIt; } bool operator==(const RowIterator& it) const { return mColIndexIt == it.mColIndexIt; } bool operator!=(const RowIterator& it) const {return !(*this == it);} const Scalar& scalar() const {return *mScalarIt;} const ColIndex& index() const {return *mColIndexIt;} void setScalar(const Scalar scalar) {*mScalarIt = scalar;} void setIndex(const ColIndex index) {*mColIndexIt = index;} private: friend class SparseMatrix; RowIterator( ColIndex* const indicesIt, Scalar* const scalarIt ): mColIndexIt(indicesIt), mScalarIt(scalarIt) { } ColIndex* mColIndexIt; Scalar* mScalarIt; }; bool debugAssertValid() const; private: MATHICGB_NO_INLINE void growEntryCapacity(); /// Contains information about a row in the matrix. struct Row { Row(): mScalarsBegin(0), mScalarsEnd(0), mIndicesBegin(0), mIndicesEnd(0) {} Scalar* mScalarsBegin; Scalar* mScalarsEnd; ColIndex* mIndicesBegin; ColIndex* mIndicesEnd; bool empty() const {return mIndicesBegin == mIndicesEnd;} ColIndex size() const { return static_cast(std::distance(mIndicesBegin, mIndicesEnd)); } }; std::vector mRows; /// Memory is allocated a block at a time. This avoids the need for copying /// that a std::vector normally does on reallocation. Believe it or not, /// copying sparse matrix memory due to reallocation was accounting for 5% /// of the running time before this change. struct Block { Block(): mPreviousBlock(0), mHasNoRows(true) {} Block(Block&& block): mColIndices(std::move(block.mColIndices)), mScalars(std::move(block.mScalars)), mPreviousBlock(block.mPreviousBlock), mHasNoRows(block.mHasNoRows) { block.mPreviousBlock = 0; block.mHasNoRows = true; } void swap(Block& block) { std::swap(mColIndices, block.mColIndices); std::swap(mScalars, block.mScalars); std::swap(mPreviousBlock, block.mPreviousBlock); std::swap(mHasNoRows, block.mHasNoRows); } Block& operator=(Block&& block) { this->~Block(); new (this) Block(std::move(block)); return *this; } size_t memoryUse() const; size_t memoryUseTrimmed() const; /// We need a RawVector here to tie the checks for the need to reallocate /// together between mColIndices and mEntries. We only need to check /// the capacity once, which, believe it or not, is a significant performance /// win. Not least because it decreases the amount of code and therefore /// causes better compiler inlining decisions. RawVector mColIndices; RawVector mScalars; Block* mPreviousBlock; /// is null if there are no previous blocks bool mHasNoRows; /// true if no rows have been made from this block yet }; Block mBlock; size_t mMemoryQuantum; }; template void SparseMatrix::appendRow( std::vector const& v, const ColIndex leadCol ) { #ifdef MATHICGB_DEBUG for (auto col = leadCol; col < leadCol; ++col) { MATHICGB_ASSERT(v[col] == 0); } #endif const auto count = static_cast(v.size()); for (ColIndex col = leadCol; col < count; ++col) { MATHICGB_ASSERT(v[col] < std::numeric_limits::max()); if (v[col] != 0) appendEntry(col, static_cast(v[col])); } rowDone(); } inline void swap(SparseMatrix& a, SparseMatrix& b) { a.swap(b); } std::ostream& operator<<(std::ostream& out, const SparseMatrix& matrix); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/StaticMonoMap.hpp000077500000000000000000000323771311555162500217440ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_STATIC_MONO_LOOKUP_GUARD #define MATHICGB_STATIC_MONO_LOOKUP_GUARD #include "SigPolyBasis.hpp" #include "PolyBasis.hpp" #include "MonoLookup.hpp" #include "PolyRing.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN /// Data structure for performing queries on a set of monomials. /// This is static in the sense that the interface is not virtual. template< /// Will use mathic::DivList or mathic::KDTree depending on this value. bool UseKDTree, /// Thing to store along with each monomial in the data structure. class Data, /// Indicate whether elements should be allowed to be removed from the /// data structure. There can be a slight performance benefit from /// disallowing removal. bool AllowRemovals, /// Whether to use bit vectors of features to speed up divisibility /// checks. This is usually a big speed up. bool UseDivMask > class StaticMonoLookup; template class StaticMonoLookup { private: typedef PolyRing::Monoid Monoid; typedef Monoid::ConstMonoRef ConstMonoRef; typedef Monoid::ConstMonoPtr ConstMonoPtr; typedef MonoLookup::EntryOutput EntryOutput; /// Configuration for a Mathic KDTree or DivList. class Configuration { public: Configuration(const Monoid& monoid): mMonoid(monoid) {} const Monoid& monoid() const {return mMonoid;} typedef int Exponent; typedef ConstMonoRef Monomial; class Entry { public: Entry(): mEntry() {} template Entry(ConstMonoRef mono, D&& data): mEntry(mono.ptr(), std::forward(data)) {} ConstMonoRef mono() const {return *mEntry.first;} const Data& data() const {return mEntry.second;} Data& data() {return mEntry.second;} private: // Store in a std::pair so that if Data has no members then no space // will be used on it. Here we are depending on std::pair to be using // the empty base class optimization. std::pair mEntry; }; Exponent getExponent(const Monomial& m, size_t var) const { return monoid().exponent(m, var); } Exponent getExponent(const Entry& e, size_t var) const { return monoid().exponent(e.mono(), var); } bool divides(const Monomial& a, const Monomial& b) const { return monoid().dividesWithComponent(a, b); } bool divides(const Entry& a, const Monomial& b) const { return monoid().dividesWithComponent(a.mono(), b); } bool divides(const Monomial& a, const Entry& b) const { return monoid().dividesWithComponent(a, b.mono()); } bool divides(const Entry& a, const Entry& b) const { return monoid().dividesWithComponent(a.mono(), b.mono()); } bool getSortOnInsert() const {return false;} template bool isLessThan(const A& a, const B& b) const { MATHICGB_ASSERT(false); return false; } size_t getVarCount() const {return monoid().varCount();} static const bool UseTreeDivMask = DM; static const bool UseLinkedList = false; static const bool UseDivMask = DM; static const size_t LeafSize = 1; static const bool PackedTree = true; static const bool AllowRemovals = AR; bool getUseDivisorCache() const {return true;} bool getMinimizeOnInsert() const {return false;} bool getDoAutomaticRebuilds() const {return UseDivMask;} double getRebuildRatio() const {return 0.5;} size_t getRebuildMin() const {return 50;} private: const Monoid& mMonoid; }; public: typedef typename std::conditional< UseKDTree, mathic::KDTree, mathic::DivList >::type BaseLookup; typedef typename BaseLookup::Entry Entry; static_assert (!Configuration::UseTreeDivMask || Configuration::UseDivMask, ""); StaticMonoLookup(const Monoid& monoid): mLookup(Configuration(monoid)) {} const Monoid& monoid() const {return mLookup.getConfiguration().monoid();} template class LambdaWrap { public: LambdaWrap(Lambda& lambda): mLambda(lambda) {} bool proceed(const Entry& entry) const {return mLambda(entry);} private: Lambda& mLambda; }; template static LambdaWrap lambdaWrap(Lambda& lambda) { return LambdaWrap(lambda); } template void forAll(Lambda&& lambda) const { const auto wrap = [&](const Entry& entry){ lambda(entry); return true; }; auto outerWrap = lambdaWrap(wrap); mLookup.forAll(outerWrap); } // *** Signature specific functionality size_t regularReducer( ConstMonoRef sig, ConstMonoRef mono, const SigPolyBasis& sigBasis, const bool preferSparseReducers ) const { SigPolyBasis::StoredRatioCmp ratioCmp(sig, mono, sigBasis); const auto& basis = sigBasis.basis(); auto reducer = size_t(-1); auto proceed = [&, this](const Entry& e) { if (ratioCmp.compare(e.data()) != GT) return true; if (reducer != size_t(-1)) { if (preferSparseReducers) { const auto newTermCount = basis.poly(e.data()).termCount(); const auto oldTermCount = basis.poly(reducer).termCount(); if (newTermCount > oldTermCount) return true; // what we already have is sparser // resolve ties by picking oldest if (newTermCount == oldTermCount && e.data() > reducer) return true; } else { // pick oldest if (e.data() > reducer) return true; // what we already have is older } } reducer = e.data(); return true; }; auto wrap = lambdaWrap(proceed); mLookup.findAllDivisors(mono, wrap); return reducer; } void lowBaseDivisors( std::vector& divisors, const size_t maxDivisors, const size_t newGenerator, const SigPolyBasis& basis ) const { MATHICGB_ASSERT(newGenerator < basis.size()); auto proceed = [&](const Entry& entry) { if (entry.data() >= newGenerator) return true; for (size_t j = 0; j <= divisors.size(); ++j) { if (j == divisors.size()) { divisors.push_back(entry.data()); break; } int cmp = basis.ratioCompare(entry.data(), divisors[j]); if (cmp == EQ && (entry.data() < divisors[j])) cmp = GT; // prefer minimum index to ensure deterministic behavior if (cmp == GT) { divisors.insert(divisors.begin() + j, entry.data()); break; } } if (divisors.size() > maxDivisors) divisors.pop_back(); MATHICGB_ASSERT(divisors.size() <= maxDivisors); return true; }; divisors.clear(); divisors.reserve(maxDivisors + 1); auto wrap = lambdaWrap(proceed); mLookup.findAllDivisors(basis.signature(newGenerator), wrap); } size_t highBaseDivisor( const size_t newGenerator, const SigPolyBasis& basis ) const { MATHICGB_ASSERT(newGenerator < basis.size()); auto highDivisor = size_t(-1); auto proceed = [&](const Entry& entry) { if (entry.data() >= newGenerator) return true; if (highDivisor != size_t(-1)) { int cmp = basis.ratioCompare(highDivisor, entry.data()); if (cmp == LT) return true; if (cmp == EQ && (entry.data() > highDivisor)) return true; // prefer minimum index to ensure deterministic behavior } highDivisor = entry.data(); return true; }; auto wrap = lambdaWrap(proceed); mLookup.findAllDivisors(basis.leadMono(newGenerator), wrap); return highDivisor; } size_t minimalLeadInSig( ConstMonoRef sig, const SigPolyBasis& basis ) const { // Given signature sig, we want to minimize (S/G)g where // g and G are the lead term and signature taken over basis elements // whose signature G divide S. The code here instead maximizes G/g, // which is equivalent and also faster since the basis has a data // structure to accelerate comparisons between the ratio of // signature to lead term. // // In case of ties, we select the sparser elements. If there is // still a tie, we select the basis element with the largest // signature. There can be no further ties since all basis // elements have distinct signatures. auto minLeadGen = size_t(-1); auto proceed = [&](const Entry& entry) { if (minLeadGen != size_t(-1)) { const int ratioCmp = basis.ratioCompare(entry.data(), minLeadGen); if (ratioCmp == LT) return true; if (ratioCmp == EQ) { // If same lead monomial in signature, pick the one with fewer terms // as that one might be less effort to reduce. const size_t minTerms = basis.poly(minLeadGen).termCount(); const size_t terms = basis.poly(entry.data()).termCount(); if (minTerms > terms) return true; if (minTerms == terms) { // If same number of terms, pick the one with larger signature // before being multiplied into the same signature. That one // might be more reduced as the constraint on regular reduction // is less. Also, as no two generators have same signature, this // ensures deterministic behavior. const auto minSig = basis.signature(minLeadGen); const auto genSig = basis.signature(entry.data()); const auto sigCmp = basis.monoid().compare(minSig, genSig); if (basis.monoid().lessThan(genSig, minSig)) return true; } } } minLeadGen = entry.data(); return true; }; auto wrap = lambdaWrap(proceed); mLookup.findAllDivisors(sig, wrap); return minLeadGen; } // *** Classic GB specific functionality size_t classicReducer( ConstMonoRef mono, const PolyBasis& basis, const bool preferSparseReducers ) const { auto reducer = size_t(-1); auto proceed = [&](const Entry& entry) { if (reducer == size_t(-1)) { reducer = entry.data(); return true; } if (preferSparseReducers) { const auto oldTermCount = basis.poly(reducer).termCount(); const auto newTermCount = basis.poly(entry.data()).termCount(); if (oldTermCount > newTermCount) { reducer = entry.data(); // prefer sparser return true; } if (oldTermCount < newTermCount) return true; } // break ties by age if (reducer > entry.data()) reducer = entry.data(); // prefer older return true; }; auto wrap = lambdaWrap(proceed); mLookup.findAllDivisors(mono, wrap); return reducer; } // *** General functionality const Entry* divisor(ConstMonoRef mono) const { return mLookup.findDivisor(mono); } void divisors(ConstMonoRef mono, EntryOutput& consumer) const { auto proceed = [&](const Entry& e) {return consumer.proceed(e.data());}; auto wrap = lambdaWrap(proceed); mLookup.findAllDivisors(mono, wrap); } void multiples(ConstMonoRef mono, EntryOutput& consumer) const { auto proceed = [&](const Entry& e) {return consumer.proceed(e.data());}; auto wrap = lambdaWrap(proceed); mLookup.findAllMultiples(mono, wrap); } void removeMultiples(ConstMonoRef mono) { mLookup.removeMultiples(mono); } void remove(ConstMonoRef mono) {mLookup.removeElement(mono);} size_t size() const {return mLookup.size();} std::string getName() const {return mLookup.getName();} const PolyRing& ring() const {return mLookup.configuration().ring();} size_t getMemoryUse() const {return mLookup.getMemoryUse();} template void insert(ConstMonoRef mono, D&& data) { mLookup.insert(Entry(mono, std::forward(data))); } private: BaseLookup mLookup; }; /// Function for creating statically compiled classes that use /// StaticMonoLookup based on run-time values. /// /// The type Functor must have an interface that is compatible with the /// following example. /// /// template /// struct Functor { /// static ReturnType make(const Params& params) { /// // do your thing /// } /// }; template< template class Functor, class ReturnType, class Params > ReturnType staticMonoLookupMake( int type, bool allowRemovals, Params&& params ) { switch (type) { case 1: if (allowRemovals) return Functor<0, 1, 1>::make(std::forward(params)); else return Functor<0, 0, 1>::make(std::forward(params)); case 2: if (allowRemovals) return Functor<1, 1, 1>::make(std::forward(params)); else return Functor<1, 0, 1>::make(std::forward(params)); case 3: if (allowRemovals) return Functor<0, 1, 0>::make(std::forward(params)); else return Functor<0, 0, 0>::make(std::forward(params)); case 4: if (allowRemovals) return Functor<1, 1, 0>::make(std::forward(params)); else return Functor<1, 0, 0>::make(std::forward(params)); default: MATHICGB_ASSERT_NO_ASSUME(false); throw std::runtime_error("Unknown code for monomial data structure"); } } MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/TypicalReducer.cpp000077500000000000000000000156061311555162500221340ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "TypicalReducer.hpp" #include "SigPolyBasis.hpp" #include "PolyBasis.hpp" #include "MathicIO.hpp" #include MATHICGB_NAMESPACE_BEGIN unsigned int TypicalReducer::preferredSetSize() const { return 1; } void TypicalReducer::reset() { mArena.freeAllAllocs(); resetReducer(); } size_t TypicalReducer::getMemoryUse() const { return mArena.getMemoryUse(); } std::unique_ptr TypicalReducer::regularReduce( ConstMonoRef sig, ConstMonoRef multiple, size_t basisElement, const SigPolyBasis& basis) { const PolyRing& ring = basis.ring(); const auto& monoid = ring.monoid(); monomial tproduct = ring.allocMonomial(mArena); monomial u = ring.allocMonomial(mArena); monoid.multiply(multiple, basis.leadMono(basisElement), tproduct); auto reducer = basis.regularReducer(sig, tproduct); if (reducer == static_cast(-1)) { mArena.freeAllAllocs(); return nullptr; // singular reduction: no regular top reduction possible } monoid.divide(basis.leadMono(reducer), tproduct, u); coefficient coef; ring.coefficientSet(coef, 1); insertTail(const_term(coef, Monoid::toOld(multiple)), &basis.poly(basisElement)); MATHICGB_ASSERT(ring.coefficientIsOne(basis.leadCoef(reducer))); ring.coefficientFromInt(coef, -1); insertTail(const_term(coef, u), &basis.poly(reducer)); basis.basis().usedAsReducer(reducer); auto result = make_unique(ring); unsigned long long steps = 2; // number of steps in this reduction for (const_term v; leadTerm(v);) { MATHICGB_ASSERT(v.coeff != 0); reducer = basis.regularReducer(sig, v.monom); if (reducer == static_cast(-1)) { // no reducer found result->append(v.coeff, v.monom); removeLeadTerm(); } else { // reduce by reducer ++steps; basis.basis().usedAsReducer(reducer); monomial mon = ring.allocMonomial(mArena); monoid.divide(basis.leadMono(reducer), v.monom, mon); ring.coefficientDivide(v.coeff, basis.leadCoef(reducer), coef); ring.coefficientNegateTo(coef); removeLeadTerm(); insertTail(const_term(coef, mon), &basis.poly(reducer)); } } if (!result->isZero()) result->makeMonic(); reset(); return result; } std::unique_ptr TypicalReducer::classicReduce(const Poly& poly, const PolyBasis& basis) { monomial identity = basis.ring().allocMonomial(mArena); basis.ring().monomialSetIdentity(identity); insert(identity, &poly); return classicReduce(basis); } std::unique_ptr TypicalReducer::classicTailReduce(const Poly& poly, const PolyBasis& basis) { MATHICGB_ASSERT(&poly.ring() == &basis.ring()); MATHICGB_ASSERT(!poly.isZero()); term identity; identity.monom = basis.ring().allocMonomial(mArena); basis.ring().monomialSetIdentity(identity.monom); basis.ring().coefficientSetOne(identity.coeff); insertTail(identity, &poly); std::unique_ptr result(new Poly(basis.ring())); result->append(poly.leadCoef(), poly.leadMono()); return classicReduce(std::move(result), basis); } std::unique_ptr TypicalReducer::classicReduceSPoly( const Poly& a, const Poly& b, const PolyBasis& basis ) { const auto& ring = basis.ring(); const auto& monoid = basis.ring().monoid(); monomial lcm = ring.allocMonomial(); monoid.lcm(a.leadMono(), b.leadMono(), lcm); // insert tail of multiple of a monomial multiple1 = ring.allocMonomial(); monoid.divide(a.leadMono(), lcm, multiple1); coefficient plusOne; ring.coefficientSet(plusOne, 1); insertTail(const_term(plusOne, multiple1), &a); // insert tail of multiple of b monomial multiple2 = ring.allocMonomial(); monoid.divide(b.leadMono(), lcm, multiple2); coefficient minusOne = plusOne; ring.coefficientNegateTo(minusOne); insertTail(const_term(minusOne, multiple2), &b); std::unique_ptr reduced = classicReduce(basis); ring.freeMonomial(lcm); ring.freeMonomial(multiple1); ring.freeMonomial(multiple2); return std::move(reduced); } void TypicalReducer::classicReduceSPolySet (std::vector >& spairs, const PolyBasis& basis, std::vector >& reducedOut) { for (auto it = spairs.begin(); it != spairs.end(); ++it) { auto reducedSPoly = classicReduceSPoly(basis.poly(it->first), basis.poly(it->second), basis); if (!reducedSPoly->isZero()) reducedOut.push_back(std::move(reducedSPoly)); } } void TypicalReducer::classicReducePolySet (const std::vector >& polys, const PolyBasis& basis, std::vector >& reducedOut) { for (auto it = polys.begin(); it != polys.end(); ++it) { auto reducedPoly = classicReduce(**it, basis); if (!reducedPoly->isZero()) reducedOut.push_back(std::move(reducedPoly)); } } void TypicalReducer::setMemoryQuantum(size_t quantum) { } std::unique_ptr TypicalReducer::classicReduce (std::unique_ptr result, const PolyBasis& basis) { const auto& ring = basis.ring(); const auto& monoid = ring.monoid(); MATHICGB_ASSERT(&result->ring() == &ring); if (tracingLevel > 100) std::cerr << "Classic reduction begun." << std::endl; coefficient coef; unsigned long long steps = 0; // number of steps in this reduction for (const_term v; leadTerm(v);) { if (tracingLevel > 100) { std::cerr << "from reducer queue: "; basis.ring().monomialDisplay(std::cerr, v.monom); std::cerr << std::endl; } size_t reducer = basis.classicReducer(v.monom); if (reducer == static_cast(-1)) { // no reducer found MATHICGB_ASSERT( result->isZero() || basis.monoid().lessThan(v.monom, result->backMono()) ); result->append(v.coeff, v.monom); removeLeadTerm(); } else { // reduce by reducer ++steps; basis.usedAsReducer(reducer); monomial mon = ring.allocMonomial(mArena); monoid.divide(basis.leadMono(reducer), v.monom, mon); ring.coefficientDivide(v.coeff, basis.leadCoef(reducer), coef); ring.coefficientNegateTo(coef); removeLeadTerm(); insertTail(const_term(coef, mon), &basis.poly(reducer)); if (tracingLevel > 100) { std::cerr << "Reducing by basis element " << reducer << ": "; MathicIO<>().writePoly(basis.poly(reducer), false, std::cerr); std::cerr << std::endl; std::cerr << "multiplied by: " << coef << " * "; basis.ring().monomialDisplay(std::cerr, mon); std::cerr << std::endl; } } } if (!result->isZero()) result->makeMonic(); if (tracingLevel > 100) std::cerr << "Classic reduction done." << std::endl; reset(); return std::move(result); } std::unique_ptr TypicalReducer::classicReduce(const PolyBasis& basis) { return classicReduce(make_unique(basis.ring()), basis); } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/TypicalReducer.hpp000077500000000000000000000057411311555162500221400ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_TYPICAL_REDUCER_GUARD #define MATHICGB_TYPICAL_REDUCER_GUARD #include "Reducer.hpp" #include "Poly.hpp" #include "PolyRing.hpp" MATHICGB_NAMESPACE_BEGIN class SigPolyBasis; class PolyBasis; /** Uses the template method pattern (not C++ templates) to implement reduction with some steps left to sub-classes. The template method pattern defines an algorithm that calls several virtual methods. Sub-classes can then redefine those methods to change some parts of the algorithm without recoding the whole thing. The word "template" here has nothing to do with C++ templates. See http://en.wikipedia.org/wiki/Template_method_pattern */ class TypicalReducer : public Reducer { public: virtual unsigned int preferredSetSize() const; virtual std::unique_ptr regularReduce( ConstMonoRef sig, ConstMonoRef multiple, size_t basisElement, const SigPolyBasis& basis ); virtual std::unique_ptr classicReduce (const Poly& poly, const PolyBasis& basis); virtual std::unique_ptr classicTailReduce (const Poly& poly, const PolyBasis& basis); virtual std::unique_ptr classicReduceSPoly (const Poly& a, const Poly& b, const PolyBasis& basis); virtual void classicReduceSPolySet( std::vector >& spairs, const PolyBasis& basis, std::vector >& reducedOut ); virtual void classicReducePolySet( const std::vector >& polys, const PolyBasis& basis, std::vector >& reducedOut ); virtual void setMemoryQuantum(size_t quantum); protected: // These are the methods that sub-classes define in order to carry // out sub-steps in the reduction. virtual void insertTail(const_term multiplier, const Poly* f) { MATHICGB_ASSERT(f != 0); NewConstTerm t = {multiplier.coeff, multiplier.monom}; insertTail(t, *f); } virtual void insert(monomial multiplier, const Poly* f) { MATHICGB_ASSERT(f != 0); ConstMonoRef mono = multiplier; insert(mono, *f); } virtual bool leadTerm(const_term& result) { NewConstTerm t; auto hasLead = leadTerm(t); if (hasLead) { result.monom = Monoid::toOld(*t.mono); result.coeff = t.coef; } return hasLead; } virtual void insertTail(NewConstTerm multiplier, const Poly& f) {} virtual void insert(ConstMonoRef multiplier, const Poly& f) {} virtual bool leadTerm(NewConstTerm& lead) {return false;} virtual void removeLeadTerm() = 0; virtual void resetReducer() = 0; virtual size_t getMemoryUse() const; // Sub-classes can use this memt::Arena mArena; private: void reset(); std::unique_ptr classicReduce(const PolyBasis& basis); std::unique_ptr classicReduce (std::unique_ptr partialResult, const PolyBasis& basis); }; MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/Unchar.hpp000077500000000000000000000026031311555162500204330ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_UNCHAR_GUARD #define MATHICGB_UNCHAR_GUARD #include MATHICGB_NAMESPACE_BEGIN /// std::ostream and std::istream handle characters differently from /// other integers. That is not desired when using char as an /// integer. Use Unchar and unchar() to cast chars to a different type /// that get handled as other integers do. template struct Unchar {typedef T type;}; // Strange but true: char, signed char and unsigned char are 3 // distinct types. Also, the signedness of char is unspecified. This // is in contrast to all the other built-in types. For example, int // and signed int are always the exact same type. namespace UncharInternal { // Two cases depending on whether char is signed or not. template::value> struct ExtendedChar {typedef signed short type;}; template<> struct ExtendedChar {typedef unsigned short type;}; }; template<> struct Unchar { typedef UncharInternal::ExtendedChar<>::type type; }; template<> struct Unchar {typedef short type;}; template<> struct Unchar {typedef unsigned short type;}; template typename Unchar::type unchar(const T& t) {return t;} MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/io-util.cpp000077500000000000000000000057161311555162500206000ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "stdinc.h" #include "io-util.hpp" #include "Poly.hpp" #include "ModuleMonoSet.hpp" #include "io-util.hpp" #include "Scanner.hpp" #include "MathicIO.hpp" #include "SigPolyBasis.hpp" #include "SignatureGB.hpp" #include "Basis.hpp" #include "PolyBasis.hpp" #include #include #include #include MATHICGB_NAMESPACE_BEGIN std::unique_ptr polyParseFromString(const PolyRing *R, const std::string &s) { std::istringstream in(s); Scanner scanner(in); return make_unique(MathicIO<>().readPoly(*R, false, scanner)); } std::string toString(const Poly *g) { std::ostringstream o; MathicIO<>().writePoly(*g, true, o); return o.str(); } std::unique_ptr basisParseFromString(std::string str) { std::istringstream inStream(str); Scanner in(inStream); auto p = MathicIO<>().readRing(true, in); auto& ring = *p.first.release(); // todo: fix leak return make_unique(MathicIO<>().readBasis(ring, false, in)); } std::unique_ptr ringFromString(std::string ringStr) { std::stringstream inStream(ringStr); Scanner in(inStream); return MathicIO<>().readRing(true, in).first; } Monomial stringToMonomial(const PolyRing *R, std::string mon) { Monomial result = R->allocMonomial(); std::stringstream ifil(mon); R->monomialParse(ifil, result); return result; } std::string monomialToString(const PolyRing *R, const Monomial& mon) { std::ostringstream o; R->monomialDisplay(o,mon); return o.str(); } monomial monomialParseFromString(const PolyRing *R, std::string mon) { // This is poor code, to only be used for testing! monomial result = R->allocMonomial(); std::stringstream ifil(mon); R->monomialParse(ifil, result); return result; } std::string monomialDisplay(const PolyRing *R, const_monomial mon) { std::ostringstream o; R->monomialDisplay(o,mon); return o.str(); } //////////////////////////////////////////////////////////////// std::string toString(SigPolyBasis *I) { std::ostringstream o; for (size_t i=0; isize(); i++) { o << " "; MathicIO<>().writePoly(I->poly(i), false, o); o << std::endl; } return o.str(); } std::string toString(SigPolyBasis *I, int) { std::ostringstream o; I->display(o); return o.str(); } std::string toString(ModuleMonoSet* H) { std::ostringstream o; H->display(o); return o.str(); } std::string toString(Basis *I) { std::ostringstream o; for (size_t i=0; isize(); i++) { o << " "; MathicIO<>().writePoly(*I->getPoly(i), false, o); o << std::endl; } return o.str(); } void output(std::ostream &o, const PolyBasis &I) { for (size_t i = 0; i < I.size(); i++) { if (!I.retired(i)) { MathicIO<>().writePoly(I.poly(i), false, o); o << std::endl; } } } MATHICGB_NAMESPACE_END mathicgb-master/src/mathicgb/io-util.hpp000077500000000000000000000023701311555162500205760ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_IO_UTIL_GUARD #define MATHICGB_IO_UTIL_GUARD #include "PolyRing.hpp" MATHICGB_NAMESPACE_BEGIN class Poly; class SigPolyBasis; class ModuleMonoSet; class PolyBasis; class Basis; std::unique_ptr ringFromString(std::string ringinfo); monomial monomialFromString(const PolyRing *R, std::string mon); monomial monomialParseFromString(const PolyRing *R, std::string mon); std::string monomialToString(const PolyRing *R, const_monomial mon); std::string monomialDisplay(const PolyRing *R, const_monomial mon); Monomial stringToMonomial(const PolyRing *R, std::string mon); std::string monomialToString(const PolyRing *R, const Monomial& mon); std::string toString(SigPolyBasis *); std::string toString(ModuleMonoSet *); std::string toString(SigPolyBasis *, int unused); // also displays signature std::string toString(Basis *); std::string toString(const Poly *); std::unique_ptr basisParseFromString(std::string str); std::unique_ptr polyParseFromString (const PolyRing *R, const std::string &s); void output(std::ostream &o, const PolyBasis &I); MATHICGB_NAMESPACE_END #endif mathicgb-master/src/mathicgb/mtbb.hpp000077500000000000000000000130551311555162500201420ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_M_TBB_GUARD #define MATHICGB_M_TBB_GUARD #ifndef MATHICGB_NO_TBB #include MATHICGB_NAMESPACE_BEGIN /// A compatibility layer for tbb. If we are compiling with tbb present, then /// these classes will simply be the same classes as in tbb. However, if we /// are compiling without tbb (so without parallelism), then these classes will /// be trivial non-parallel implementations that allows MathicGB to work /// without tbb being present. TBB doesn't work on Cygwin, so that is at least /// one good reason to have this compatibility layer. This only works if all /// uses of tbb go through mtbb, so make sure to do that. namespace mtbb { using ::tbb::task_scheduler_init; using ::tbb::mutex; using ::tbb::parallel_do_feeder; using ::tbb::enumerable_thread_specific; using ::tbb::parallel_do; using ::tbb::parallel_for; using ::tbb::parallel_sort; using ::tbb::blocked_range; using ::tbb::tick_count; } MATHICGB_NAMESPACE_END #else #include #include #include #include #include MATHICGB_NAMESPACE_BEGIN namespace mtbb { class task_scheduler_init { public: task_scheduler_init(int) {} static const int automatic = 1; }; class mutex { public: mutex(): mLocked(false) {} class scoped_lock { public: scoped_lock(): mMutex(0) {} scoped_lock(mutex& m): mMutex(&m) {mMutex->lock();} ~scoped_lock() { if (mMutex != 0) release(); } void acquire(mutex& m) { MATHICGB_ASSERT(mMutex == 0); mMutex = &m; } bool try_acquire(mutex& m) { MATHICGB_ASSERT(mMutex == 0); if (!m.try_lock()) return false; mMutex = &m; return true; } void release() { MATHICGB_ASSERT(mMutex != 0); mMutex->unlock(); mMutex = 0; } private: mutex* mMutex; }; void lock() { MATHICGB_ASSERT(!mLocked); // deadlock mLocked = true; } bool try_lock() { if (mLocked) return false; lock(); return true; } void unlock() { MATHICGB_ASSERT(mLocked); mLocked = false; } private: bool mLocked; }; template class enumerable_thread_specific { public: template enumerable_thread_specific(Op&& creater): mCreater(creater) {} bool empty() const {return mObj.get() == 0;} T& local() { if (empty()) mObj = make_unique(mCreater()); MATHICGB_ASSERT(!empty()); return *mObj; } T* begin() { if (empty()) return 0; else return mObj.get(); } T* end() { if (empty()) return 0; else return begin() + 1; } void clear() { mObj.reset(0); } private: std::function mCreater; std::unique_ptr mObj; }; template class blocked_range { public: typedef size_t size_type; typedef Value const_iterator; blocked_range(Value begin, Value end, size_t grainSize = 1): mBegin(begin), mEnd(end), mGrainSize(grainSize) {} size_type size() const {return end() - begin();} bool empty() const {return mBegin == mEnd;} size_type grainsize() const {return mGrainSize;} bool is_divisible() const {return false;} const_iterator begin() const {return mBegin;} const_iterator end() const {return mEnd;} private: const_iterator mBegin; const_iterator mEnd; size_type mGrainSize; }; template void parallel_for(Range&& range, Func&& f) { f(range); } template void parallel_for(Index begin, Index end, Index step, Func&& f) { for (auto i = begin; i < end; i += step) f(i); } template class parallel_do_feeder { public: parallel_do_feeder(std::vector& tasks): mTasks(tasks) {} template void add(TT&& t) {mTasks.push_back(std::forward(t));} private: std::vector& mTasks; }; template void parallel_do(InputIterator begin, InputIterator end, Body body) { typedef typename std::remove_reference::type Task; std::vector tasks; parallel_do_feeder feeder(tasks); for (; begin != end; ++begin) { tasks.push_back(*begin); while (!tasks.empty()) { auto task = std::move(tasks.back()); tasks.pop_back(); body(task, feeder); } } } template void parallel_sort(It begin, It end, Pred&& pred) { std::sort(begin, end, pred); } class tick_count { private: // This really should be std::chrono::steady_clock, but GCC 4.5.3 doesn't // have that. typedef std::chrono::system_clock clock; public: tick_count(): mTime() {} static tick_count now() { tick_count t; t.mTime = clock::now(); return t; } class interval_t { public: interval_t(double seconds): mSeconds(seconds) {} double seconds() const {return mSeconds;} private: const double mSeconds; }; interval_t operator-(const tick_count t) const { typedef std::chrono::duration SecondDuration; const auto duration = std::chrono::duration_cast(mTime - t.mTime); return duration.count(); } private: clock::time_point mTime; }; } MATHICGB_NAMESPACE_END #endif #endif mathicgb-master/src/mathicgb/stdinc.h000077500000000000000000000301771311555162500201460ustar00rootroot00000000000000#ifdef MATHICGB_STDINC_GUARD #error stdinc.h included twice. Only include stdinc.h once per cpp file. #endif #define MATHICGB_STDINC_GUARD #ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++. /// Sometimes you know that a function will be called very rarely so you want to /// tell the compiler not to inline it even if it could be inlined at only a /// modest increase in code size. That is what MATHICGB_NO_INLINE does. #define MATHICGB_NO_INLINE __declspec(noinline) /// Sometimes the compiler just will not inline functions that should /// be inlined. Use sparingly --- preferably only if a profiler says /// that a tiny often-called function consumes a significant amount of time. #define MATHICGB_INLINE __forceinline /// Tells the compiler to always assume that the expression X is true. #define MATHICGB_ASSUME(X) __assume(X) /// As MATHICGB_ASSUME, but might actually evaluate X at run-time if it has /// side-effects. The point is that this can be used on compilers with no other /// support for assuming things. So there is no difference on MS VC++. #define MATHICGB_ASSUME_AND_MAY_EVALUATE(X) __assume(X) /// Tells the compiler that this function returns a pointer that is not an alias /// for any other point that is currently valid in the program - like malloc. #define MATHICGB_RETURN_NO_ALIAS __declspec(restrict) /// Tells the compiler that this function will never throw an exception. #define MATHICGB_NOTHROW __declspec(nothrow) /// Tells the compiler that this function has no effects except the return value /// and the return value depends only on the arguments and first-level /// indirections of the arguments. (this is the common denominator of GCC /// and MS VC++ capabilities) #define MATHICGB_PURE __declspec(noalias) /// Tells the compiler that the return value of this function must be looked /// at by the caller. For example this is appropriate for realloc. #define MATHICGB_MUST_CHECK_RETURN_VALUE /// Tells the compiler that the current line of code cannot be reached. #define MATHICGB_UNREACHABLE __assume(false) /// Tells the compiler that a variable that is a pointer (not a reference) /// does not alias any other pointer that is used in the current scope. #define MATHICGB_RESTRICT __restrict #pragma warning (disable: 4996) // don't warn about e.g. std::fill on pointers #pragma warning (disable: 4290) // VC++ ignores throw () specification. #pragma warning (disable: 4127) // Warns about using "while (true)". #pragma warning (disable: 4100) // Warns about unused parameters. #pragma warning (disable: 4800) // Warns on int to bool conversion. #pragma warning (disable: 4146) // Warns on unary minus on unsigned (bit trick) // This warning warns about using the this pointer in base member // initializer lists. This is a pretty good warning as that can // obviously easily go wrong, but it is pretty useful to do as well, // so the warning is turned off. #pragma warning (disable: 4355) // Tells Windows.h/Windef.h not to define macroes called min and max since that // clashes with std::numeric_limits::max and std::max and probably lots of // other things too. #define NOMINMAX #ifndef MATHICGB_USE_FAKE_ATOMIC #if defined (_M_IX86) || defined(_M_X64) // if on x86 (32 bit) or x64 (64 bit) #define MATHICGB_USE_CUSTOM_ATOMIC_X86_X64 #define MATHICGB_USE_CUSTOM_ATOMIC_4BYTE #ifdef _M_X64 // if on x64 (64 bit) #define MATHICGB_USE_CUSTOM_ATOMIC_8BYTE #endif #endif #endif #elif defined (__GNUC__) // GCC compiler #define MATHICGB_NO_INLINE __attribute__((noinline)) #define MATHICGB_INLINE __attribute__((always_inline)) inline #define MATHICGB_ASSUME(X) #define MATHICGB_ASSUME_AND_MAY_EVALUATE(X) do {if(!(X)){MATHICGB_UNREACHABLE;}while(0)} #define MATHICGB_RETURN_NO_ALIAS __attribute__(malloc) #define MATHICGB_NOTHROW __attribute__(nothrow) #define MATHICGB_PURE __attribute__(pure) #define MATHICGB_MUST_CHECK_RETURN_VALUE __attribute__(warn_unused_result) #define MATHICGB_UNREACHABLE __builtin_unreachable() #define MATHICGB_RESTRICT __restrict // if on x86 (32 bit) or x64 (64 bit) #ifndef MATHICGB_USE_FAKE_ATOMIC #if defined (_X86_) || defined(__x86_64__) #define MATHICGB_USE_CUSTOM_ATOMIC_X86_X64 #define MATHICGB_USE_CUSTOM_ATOMIC_4BYTE #ifdef __x86_64__ // if on x64 (64 bit) #define MATHICGB_USE_CUSTOM_ATOMIC_8BYTE #endif #endif #endif #else #define MATHICGB_NO_INLINE #define MATHICGB_INLINE inline #define MATHICGB_ASSUME(X) #define MATHICGB_ASSUME_AND_MAY_EVALUATE(X) #define MATHICGB_RETURN_NO_ALIAS #define MATHICGB_NOTHROW #define MATHICGB_PURE #define MATHICGB_MUST_CHECK_RETURN_VALUE #define MATHICGB_UNREACHABLE #define MATHICGB_RESTRICT #endif #if defined(__CYGWIN__) && !defined(MATHICGB_NO_TBB) #define MATHICGB_NO_TBB #endif #include #include #ifdef MATHICGB_DEBUG // don't force inline while debugging #undef MATHICGB_INLINE #define MATHICGB_INLINE inline // we have to define DEBUG as lots of code assumes that asserts are turned // on/off depending on DEBUG. Those should change to checking // MATHICGB_DEBUG and then we can remove this define. #define DEBUG #include // Useful for debugging. #include #define MATHICGB_ASSERT(X) do{assert(X);}while(0) #define MATHICGB_ASSERT_NO_ASSUME(X) MATHICGB_ASSERT(X) #define MATHICGB_IF_DEBUG(X) X #else #define MATHICGB_ASSERT(X) MATHICGB_ASSUME(X) #define MATHICGB_ASSERT_NO_ASSUME(X) #define MATHICGB_IF_DEBUG(X) #endif #ifdef MATHICGB_SLOW_DEBUG // for asserts that take a long time. #define MATHICGB_SLOW_ASSERT(X) MATHICGB_ASSERT(X) #else #define MATHICGB_SLOW_ASSERT(X) #endif /// Concatenates A to B without expanding A and B. This is achieved since /// token pasting (##) defeats macro expansion. #define MATHICGB_CONCATENATE(A,B) A##B /// Concatenates A to B after expanding A and B. This is achieved since /// macro parameters are expanded before expanding the macro itself, /// so the token pasting inside MATHICGB_CONCATENATE does not defeat /// expansion of the parameters. So even though this macro just evaluates /// directly to MATHICGB_CONCATENATE(A,B) it does not do the same thing /// as that macro does. #define MATHICGB_CONCATENATE_AFTER_EXPANSION(A,B) MATHICGB_CONCATENATE(A,B) /// Returns an identifier that will be unique in the current file. If you need /// two different identifiers on the same line, you'll need to pass in two /// different ID paramters. Otherwise the ID parameter can be any identifier. /// On the same line, the identifier will be the same if the ID is the same. /// This can be useful in some macroes. #define MATHICGB_UNIQUE(ID) \ MATHICGB_CONCATENATE_AFTER_EXPANSION( \ MathicGB_unique_identifier_, \ MATHICGB_CONCATENATE_AFTER_EXPANSION(ID,__LINE__) \ ) /// Opens the mgb namespace. The purpose of having this be a macro is /// that otherwise editors the world over would automatically indent ALL /// CODE in MathicGB by an extra level to no benefit. By hiding the /// open and close braces inside a macro, the editors cannot see it so they /// do not indent because of it. Also, while transitioning to using /// the namespace, this was a useful way to insert the proper code in /// each file while still keeping everything compiling mid-way. #define MATHICGB_NAMESPACE_BEGIN namespace mgb { #define MATHICGB_NAMESPACE_END } #include /* See http://herbsutter.com/gotw/_102/ for a reason to have a make_unique function. It's pretty easy to do, too: template std::unique_ptr make_unique( Args&& ...args ) { return std::unique_ptr( new T( std::forward(args)... ) ); } Unfortunately, MSVC does not have variadic templates, so this turns into the monstrosity of overloads below. At least they got the perfect forwarding working, otherwise this would have required 4^N overloads for N parameters! Add more overloads below if you need more parameters. */ MATHICGB_NAMESPACE_BEGIN template std::unique_ptr make_unique() { return std::unique_ptr(new T()); } template std::unique_ptr make_unique(A1&& a1) { return std::unique_ptr(new T(std::forward(a1))); } template std::unique_ptr make_unique(A1&& a1, A2&& a2) { return std::unique_ptr(new T(std::forward(a1), std::forward(a2))); } template std::unique_ptr make_unique(A1&& a1, A2&& a2, A3&& a3) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3))); } template std::unique_ptr make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3), std::forward(a4))); } template std::unique_ptr make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3), std::forward(a4), std::forward(a5))); } template std::unique_ptr make_unique (A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3), std::forward(a4), std::forward(a5), std::forward(a6))); } template std::unique_ptr make_unique (A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3), std::forward(a4), std::forward(a5), std::forward(a6), std::forward(a7))); } template std::unique_ptr make_unique (A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3), std::forward(a4), std::forward(a5), std::forward(a6), std::forward(a7), std::forward(a8))); } template std::unique_ptr make_unique (A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3), std::forward(a4), std::forward(a5), std::forward(a6), std::forward(a7), std::forward(a8), std::forward(a9))); } template std::unique_ptr make_unique (A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10) { return std::unique_ptr (new T(std::forward(a1), std::forward(a2), std::forward(a3), std::forward(a4), std::forward(a5), std::forward(a6), std::forward(a7), std::forward(a8), std::forward(a9), std::forward(a10))); } template std::unique_ptr make_unique_array(size_t count) { return std::unique_ptr(new T[count]); } // TODO: These types should be defined in some way that actually // checks that these bit counts are right like in a configure script. typedef unsigned long long uint64; typedef unsigned int uint32; typedef unsigned short uint16; typedef unsigned char uint8; typedef signed long long int64; typedef signed int int32; typedef signed short int16; typedef signed char int8; /// Bizarrely, OpenMP 2 only supports signed loop /// variables. This defect is fixed in OpenMP 3. MSVC 2012 only supports /// OpenMP 2. So signed loop indices are forced for loops that are /// parallelized using OpenMP. typedef signed long OMPIndex; static const size_t BitsPerByte = 8; static const size_t MemoryAlignment = sizeof(void*); /// The higher the value the more detailed output about what the program /// is doing. extern int tracingLevel; MATHICGB_NAMESPACE_END mathicgb-master/src/test/000077500000000000000000000000001311555162500156775ustar00rootroot00000000000000mathicgb-master/src/test/F4MatrixBuilder.cpp000077500000000000000000000136401311555162500213570ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/Poly.hpp" #include "mathicgb/PolyRing.hpp" #include "mathicgb/F4MatrixBuilder.hpp" #include "mathicgb/Basis.hpp" #include "mathicgb/PolyBasis.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/mtbb.hpp" #include "mathicgb/MathicIO.hpp" #include #include using namespace mgb; namespace { // We need a struct to keep the ring and so on alive after // construction - we cannot just return an object. // // @todo: This whole thing is fairly ridiculous - some kind of more // general dependency injection mechanism might be nice here. struct BuilderMaker { BuilderMaker(): mRing(ringFromString("101 6 1\n1 1 1 1 1 1")), mIdeal(*mRing), mBasis( *mRing, MonoLookup::makeFactory(mRing->monoid(), 1)->make(true, true) ) {} const Poly& addBasisElement(const std::string& str) { std::istringstream in(str); Scanner scanner(in); auto p = make_unique (MathicIO<>().readPoly(*mRing, false, scanner)); mBasis.insert(std::move(p)); return mBasis.poly(mBasis.size() - 1); } F4MatrixBuilder& create() { MATHICGB_ASSERT(mBuilder.get() == 0); mBuilder.reset(new F4MatrixBuilder(mBasis)); return *mBuilder; } const PolyRing& ring() const {return *mRing;} private: std::unique_ptr mRing; Basis mIdeal; PolyBasis mBasis; std::unique_ptr mBuilder; }; } TEST(F4MatrixBuilder, Empty) { for (int threadCount = 1; threadCount < 4; ++threadCount) { mgb::mtbb::task_scheduler_init scheduler(threadCount); BuilderMaker maker; F4MatrixBuilder& builder = maker.create(); QuadMatrix matrix(maker.ring()); builder.buildMatrixAndClear(matrix); ASSERT_EQ(0, matrix.topLeft.rowCount()); ASSERT_EQ(0, matrix.bottomLeft.rowCount()); ASSERT_EQ(0, matrix.topLeft.computeColCount()); ASSERT_EQ(0, matrix.topRight.computeColCount()); ASSERT_EQ(0, matrix.leftColumnMonomials.size()); ASSERT_EQ(0, matrix.rightColumnMonomials.size()); } } TEST(F4MatrixBuilder, SPair) { for (int threadCount = 1; threadCount < 4; ++threadCount) { mgb::mtbb::task_scheduler_init scheduler(threadCount); BuilderMaker maker; const Poly& p1 = maker.addBasisElement("a4c2-d"); const Poly& p2 = maker.addBasisElement("a4b+d"); // S-pair of p1 and p2 is -c2d-bd const Poly& p3 = maker.addBasisElement("c2d+3"); F4MatrixBuilder& builder = maker.create(); builder.addSPolynomialToMatrix(p1, p2); QuadMatrix qm(builder.ring()); builder.buildMatrixAndClear(qm); const char* const str1 = "Left columns: c2d\n" "Right columns: bd 1\n" "0: 0#1 | 0: 1#3 \n" " | \n" "0: 0#100 | 0: 0#100\n"; const char* const str2 = "Left columns: c2d\n" "Right columns: bd 1\n" "0: 0#1 | 0: 0#1\n" " | \n" "0: 0#1 | 0: 1#3\n"; std::string qmStr = qm.toString(); ASSERT_TRUE(str1 == qmStr || str2 == qmStr) << "\n** str1: " << str1 << "\n** qm: " << qmStr; } } TEST(F4MatrixBuilder, OneByOne) { for (int threadCount = 1; threadCount < 4; ++threadCount) { mgb::mtbb::task_scheduler_init scheduler(threadCount); BuilderMaker maker; const Poly& p = maker.addBasisElement("a"); F4MatrixBuilder& builder = maker.create(); builder.addPolynomialToMatrix(p.leadMono(), p); QuadMatrix qm(builder.ring()); builder.buildMatrixAndClear(qm); const char* str = "Left columns: a2\n" "Right columns:\n" "0: 0#1 | 0:\n" " | \n" "0: 0#1 | 0:\n"; ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm; } } TEST(F4MatrixBuilder, DirectReducers) { for (int threadCount = 1; threadCount < 4; ++threadCount) { BuilderMaker maker; maker.addBasisElement("a6"); // reducer == to lead term maker.addBasisElement("a3b2+a3c"); // reducer == to lower order term maker.addBasisElement("c"); // reducer divides maker.addBasisElement("d2"); // does not divide F4MatrixBuilder& builder = maker.create(); Poly p1(builder.ring()); { std::istringstream in("a3+b2+c+d"); Scanner scanner(in); p1 = MathicIO<>().readPoly(builder.ring(), false, scanner); builder.addPolynomialToMatrix(p1.leadMono(), p1); } Poly p2(builder.ring()); { std::istringstream in("a3+2b2+3c+4d"); Scanner scanner(in); p2 = MathicIO<>().readPoly(builder.ring(), false, scanner); builder.addPolynomialToMatrix(p2.leadMono(), p2); } QuadMatrix qm(builder.ring()); builder.buildMatrixAndClear(qm); const char* str = "Left columns: a6 a3b2 a3c\n" "Right columns: a3d\n" "0: 2#1 | 0: \n" "1: 1#1 2#1 | 1: \n" "2: 0#1 | 2: \n" " | \n" "0: 0#1 1#1 2#1 | 0: 0#1\n" "1: 0#1 1#2 2#3 | 1: 0#4\n"; qm = qm.toCanonical(); ASSERT_EQ(str, qm.toString()) << "** qm:\n" << qm; } } TEST(F4MatrixBuilder, IteratedReducer) { for (int threadCount = 1; threadCount < 4; ++threadCount) { BuilderMaker maker; const Poly& p1 = maker.addBasisElement("a4-a3"); const Poly& p2 = maker.addBasisElement("a-1"); F4MatrixBuilder& builder = maker.create(); builder.addPolynomialToMatrix(p1.leadMono(), p2); QuadMatrix qm(builder.ring()); builder.buildMatrixAndClear(qm); const char* str = "Left columns: a5 a4 a3 a2 a\n" "Right columns: 1\n" "0: 4#1 | 0: 0#100\n" "1: 3#1 4#100 | 1: \n" "2: 2#1 3#100 | 2: \n" "3: 1#1 2#100 | 3: \n" "4: 0#1 1#100 | 4: \n" " | \n" "0: 0#1 1#100 | 0: \n"; ASSERT_EQ(str, qm.toCanonical().toString()) << "** qm:\n" << qm; } } mathicgb-master/src/test/F4MatrixReducer.cpp000077500000000000000000000100631311555162500213560ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/F4MatrixReducer.hpp" #include "mathicgb/SparseMatrix.hpp" #include "mathicgb/QuadMatrix.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/Poly.hpp" #include "mathicgb/MathicIO.hpp" #include #include using namespace mgb; TEST(F4MatrixReducer, Reduce) { auto ring = ringFromString("101 6 1\n10 1 1 1 1 1"); QuadMatrix m(*ring); std::istringstream in("a4+a3+a2+a1+b5+b4+b3+b2+b1"); Scanner scanner(in); auto p = MathicIO<>().readPoly(*ring, false, scanner); size_t count = 0; for (auto it = p.begin(); it != p.end(); ++it) { if (count < 4) m.leftColumnMonomials.push_back(it.mono()); else m.rightColumnMonomials.push_back(it.mono()); ++count; } // top left m.topLeft.clear(); m.topLeft.appendEntry(0, 1); m.topLeft.appendEntry(1, 2); m.topLeft.appendEntry(3, 3); m.topLeft.rowDone(); m.topLeft.appendEntry(1, 1); m.topLeft.appendEntry(2, 3); m.topLeft.rowDone(); m.topLeft.appendEntry(2, 1); m.topLeft.appendEntry(3, 7); m.topLeft.rowDone(); m.topLeft.appendEntry(3, 1); m.topLeft.rowDone(); // top right m.topRight.clear(); m.topRight.appendEntry(2,8); m.topRight.rowDone(); m.topRight.appendEntry(3,9); m.topRight.rowDone(); m.topRight.appendEntry(4,10); m.topRight.rowDone(); m.topRight.rowDone(); // bottom left m.bottomLeft.clear(); m.bottomLeft.rowDone(); m.bottomLeft.appendEntry(1, 9); m.bottomLeft.rowDone(); m.bottomLeft.appendEntry(0, 2); m.bottomLeft.appendEntry(1, 99); // 100 = -2 mod 101 m.bottomLeft.appendEntry(2, 83); // 83 = -18 mod 101 m.bottomLeft.appendEntry(3, 6); m.bottomLeft.rowDone(); m.bottomLeft.appendEntry(0, 1); m.bottomLeft.appendEntry(1, 1); m.bottomLeft.appendEntry(3, 24); m.bottomLeft.rowDone(); m.bottomLeft.rowDone(); m.bottomLeft.appendEntry(3, 100); m.bottomLeft.rowDone(); // bottom right m.bottomRight.clear(); m.bottomRight.rowDone(); m.bottomRight.appendEntry(1, 2); m.bottomRight.appendEntry(3, 11); m.bottomRight.rowDone(); m.bottomRight.appendEntry(2, 16); m.bottomRight.appendEntry(3, 47); m.bottomRight.rowDone(); m.bottomRight.appendEntry(0, 1); m.bottomRight.appendEntry(2, 12); m.bottomRight.appendEntry(3, 13); m.bottomRight.appendEntry(4, 41); m.bottomRight.rowDone(); m.bottomRight.appendEntry(0, 2); m.bottomRight.appendEntry(1, 2); m.bottomRight.appendEntry(2, 8); m.bottomRight.appendEntry(3, 75); m.bottomRight.appendEntry(4, 90); m.bottomRight.rowDone(); m.bottomRight.appendEntry(0, 1); m.bottomRight.appendEntry(1, 1); m.bottomRight.appendEntry(2, 4); m.bottomRight.appendEntry(3, 88); m.bottomRight.appendEntry(4, 45); m.bottomRight.rowDone(); MATHICGB_ASSERT(m.debugAssertValid()); const char* origStr = "Left columns: a4 a3 a2 a\n" "Right columns: b5 b4 b3 b2 b\n" "0: 0#1 1#2 3#3 | 0: 2#8 \n" "1: 1#1 2#3 | 1: 3#9 \n" "2: 2#1 3#7 | 2: 4#10 \n" "3: 3#1 | 3: \n" " | \n" "0: | 0: \n" // zero row "1: 1#9 | 1: 1#2 3#11 \n" // becomes second row "2: 0#2 1#99 2#83 3#6 | 2: 2#16 3#47 \n" // zero on left red. "3: 0#1 1#1 3#24 | 3: 0#1 2#12 3#13 4#41 \n" // becomes first row "4: | 4: 0#2 1#2 2#8 3#75 4#90\n" // zero on right red. "5: 3#100 | 5: 0#1 1#1 2#4 3#88 4#45\n"; // zero on right red. ASSERT_EQ(origStr, m.toString()) << "Printed m:\n" << m; SparseMatrix reduced (F4MatrixReducer(ring->charac()).reducedRowEchelonFormBottomRight(m)); const char* redStr = "0: 0#1 2#4 3#22 4#11\n" "1: 1#1 3#66 4#34\n"; reduced.sortRowsByIncreasingPivots(); ASSERT_EQ(redStr, reduced.toString()) << "Printed reduced:\n" << reduced; } mathicgb-master/src/test/MathicIO.cpp000077500000000000000000000226471311555162500200560ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/MathicIO.hpp" #include using namespace mgb; TEST(MathicIO, Combined) { const char* const str = "32003 6\n" "1 1 1 1 1 1 1\n" "_revlex revcomponent\n" "3\n" " -bc+ad\n" " -b2+af\n" " -bc2+a2e\n"; std::istringstream inStream(str); Scanner in(inStream); auto p = MathicIO<>().readRing(true, in); auto& ring = *p.first; auto basis = MathicIO<>().readBasis(ring, false, in); } TEST(MathicIO, ReadWriteRing) { typedef PolyRing::Monoid Monoid; typedef Monoid::VarIndex VarIndex; typedef Monoid::Exponent Exponent; typedef PolyRing::Field BaseField; typedef BaseField::RawElement RawElement; auto check = [&]( const char* const inStr, const char* outStr, const RawElement charac, const VarIndex varCount, const VarIndex gradingCount, const bool withComponent ) { for (int i = 0; i < 2; ++i) { const char* str = i == 0 ? inStr : outStr; if (str == 0) continue; Scanner in(str); const auto p = MathicIO<>().readRing(withComponent, in); const auto& monoid = p.first->monoid(); const auto& field = p.first->field(); ASSERT_EQ(charac, field.charac()); ASSERT_EQ(varCount, monoid.varCount()); ASSERT_EQ(gradingCount, monoid.gradingCount()); std::ostringstream out; MathicIO<>().writeRing(*p.first, p.second, withComponent, out); ASSERT_EQ(outStr, out.str()); } }; check("101 2 1 3 4", "101 2\nrevlex 1\n 3 4\n", 101, 2, 1, false); check( "101 2 schreyer lex 1 3 4 _lex revcomponent", "101 2\nschreyer lex 1\n 3 4\n _lex\n revcomponent\n", 101, 2, 1, true ); check( "101 2 2 component 3 4", "101 2\nrevlex 2\n component\n 3 4\n", 101, 2, 2, true ); } TEST(MathicIO, ReadWriteMonomial) { typedef PolyRing::Monoid Monoid; typedef Monoid::VarIndex VarIndex; typedef Monoid::Exponent Exponent; static const auto NoComponent = static_cast(-1); Monoid m(28); // canonicalStr is str as it should appear after being read and // printed. If canonicalStr is null then this is the same as str. auto check = [&]( const char* const str, const Exponent component, const VarIndex var1, const Exponent exp1, const VarIndex var2, const Exponent exp2, const char* const canonicalStr ) { const bool doComponent = component != NoComponent; // read monomial from string auto monoRead = m.alloc(); Scanner in(str); MathicIO<>().readMonomial(m, doComponent, *monoRead, in); // directly make monomial auto monoSet = m.alloc(); if (var1 != -1) m.setExponent(var1, exp1, *monoSet); if (var2 != -1) m.setExponent(var2, exp2, *monoSet); if (doComponent) m.setComponent(component, *monoSet); ASSERT_TRUE(m.equal(*monoRead, *monoSet)) << "Str: " << str; // print monomial std::ostringstream out; MathicIO<>().writeMonomial(m, doComponent, *monoRead, out); const auto correctStr = canonicalStr == 0 ? str : canonicalStr; ASSERT_EQ(correctStr, out.str()); }; check("1", NoComponent, -1,-1, -1,-1, 0); check("1<0>", 0, -1,-1, -1,-1, 0); check("1<1>", 1, -1,-1, -1,-1, 0); check("1<999>", 999, -1,-1, -1,-1, 0); check("a1", NoComponent, 0,1, -1,-1, "a"); check("b10<0>", 0, 1,10, -1,-1, 0); check("A11", NoComponent, 26,11, -1,-1, 0); check("B99<1>", 1, 27,99, -1,-1, 0); check("ab", NoComponent, 0,1, 1,1, 0); check("ba", NoComponent, 0,1, 1,1, "ab"); check("a0c3b1", NoComponent, 1,1, 2,3, "bc3"); check("ab<2>", 2, 0,1, 1,1, 0); } TEST(MathicIO, ReadWriteBasis) { typedef PolyRing::Monoid Monoid; typedef PolyRing::Field Field; PolyRing ring(Field(101), Monoid(28)); auto check = [&]( const char* const inStr, const char* const outStr, const bool doComponent ) { for (int i = 0; i < 2; ++i) { const char* str = i == 0 ? inStr : outStr; if (str == 0) continue; Scanner in(str); const auto basis = MathicIO<>().readBasis(ring, doComponent, in); std::ostringstream out; MathicIO<>().writeBasis(basis, doComponent, out); const auto correctStr = outStr == 0 ? inStr : outStr; ASSERT_EQ(correctStr, out.str()); } }; check("0", "0\n", false); check("0", "0\n", true); check("1 0", "1\n 0\n", false); check("1 0", "1\n 0\n", true); check("1 1", "1\n 1\n", false); check("1 a<0>", "1\n a<0>\n", true); check("2 a b", "2\n a\n b\n", false); } TEST(MathicIO, ReadWritePoly) { typedef PolyRing::Monoid Monoid; typedef PolyRing::Field Field; PolyRing ring(Field(101), Monoid(28)); auto check = [&]( const char* const inStr, const char* const outStr, const bool doComponent ) { for (int i = 0; i < 2; ++i) { const char* str = i == 0 ? inStr : outStr; if (str == 0) continue; Scanner in(str); const auto poly = MathicIO<>().readPolyDoNotOrder(ring, doComponent, in); std::ostringstream out; MathicIO<>().writePoly(poly, doComponent, out); const auto correctStr = outStr == 0 ? inStr : outStr; ASSERT_EQ(correctStr, out.str()); } }; check("+0", "0", false); check("-0", "0", false); check("+1", "1", false); check("\t a\t", "a", false); check("3a+1b5+2c6", "3a+b5+2c6", false); check("+0", "0", true); check("-0", "0", true); check("+1<5>", "1<5>", true); check("\t a<0>\t", "a<0>", true); check("3a<1>+1b5<2>+2c6<3>", "3a<1>+b5<2>+2c6<3>", true); } TEST(MathicIO, ReadWriteTerm) { typedef PolyRing::Monoid Monoid; typedef Monoid::VarIndex VarIndex; typedef Monoid::Exponent Exponent; typedef PolyRing::Field Field; typedef Field::Element Coefficient; typedef Field::RawElement RawCoefficient; static const auto NoComponent = static_cast(-1); PolyRing ring(Field(101), Monoid(28)); auto&& m = ring.monoid(); auto&& f = ring.field(); auto check = [&]( const char* const inStr, const char* const outStr, const bool doComponent, const RawCoefficient coef ) { for (int i = 0; i < 2; ++i) { const char* str = i == 0 ? inStr : outStr; if (str == 0) continue; // read term from string auto monoRead = m.alloc(); Coefficient readCoef = f.zero(); Scanner in(str); MathicIO<>().readTerm(ring, doComponent, readCoef, *monoRead, in); ASSERT_EQ(coef, readCoef.value()); // print monomial std::ostringstream out; MathicIO<>().writeTerm (ring, doComponent, readCoef, *monoRead, false, out); const auto correctStr = outStr == 0 ? inStr : outStr; ASSERT_EQ(correctStr, out.str()); } }; check("1", 0, false, 1); check("-1", "-1", false, f.minusOne().value()); check("+1", "1", false, 1); check("2", 0, false, 2); check("+102", "1", false, 1); check("1<0>", 0, true, 1); check("+1<2>", "1<2>", true, 1); check("2<3>", 0, true, 2); check("+3<4>", "3<4>", true, 3); check("-3<4>", "-3<4>", true, f.negative(f.toElement(3)).value()); check("+1a<0>", "a<0>", true, 1); check("+2b", "2b", false, 2); } TEST(MathicIO, ReadWriteBaseField) { Scanner in("101"); auto field = MathicIO<>().readBaseField(in); ASSERT_EQ(101, field.charac()); std::ostringstream out; MathicIO<>().writeBaseField(field, out); ASSERT_EQ("101", out.str()); } TEST(MathicIO, ReadWriteOrder) { typedef PolyRing::Monoid Monoid; typedef Monoid::VarIndex VarIndex; const auto check = []( const char* const inStr, const char* const outStr, const VarIndex varCount, const VarIndex gradingCount, const bool withComponent, const bool componentsAscendingDesired, const bool schreyering ) -> void { for (int i = 0; i < 2; ++i) { const char* str = i == 0 ? inStr : outStr; if (str == 0) continue; Scanner in(str); const auto order = MathicIO<>().readOrder(varCount, withComponent, in); ASSERT_EQ(varCount, order.varCount()); ASSERT_EQ(gradingCount, order.gradingCount()) << inStr; ASSERT_EQ(componentsAscendingDesired, order.componentsAscendingDesired()); ASSERT_EQ(schreyering, order.schreyering()) << inStr; std::ostringstream out; MathicIO<>().writeOrder(order, withComponent, out); ASSERT_EQ(outStr, out.str()); } }; check("0\n", "revlex 0\n", 0, 0, 0,1,0); check("1\n 2\n", "revlex 1\n 2\n", 1, 1, 0,1,0); check("2\n 3\n 4\n", "revlex 2\n 3\n 4\n", 1, 2, 0,1,0); check("2\n 3 4\n 5 6\n", "revlex 2\n 3 4\n 5 6\n", 2, 2, 0,1,0); check("1\n 1 1 1 1\n", "revlex 1\n 1 1 1 1\n", 4, 1, 0,1,0); check("lex 0", "lex 0\n", 0, 0, 0,1,0); check("lex 1 2", "lex 1\n 2\n", 1, 1, 0,1,0); check("lex 2 3 4", "lex 2\n 3\n 4\n", 1, 2, 0,1,0); check("lex 2 3 4 5 6", "lex 2\n 3 4\n 5 6\n", 2, 2, 0,1,0); check("lex 1 1 1 1 1", "lex 1\n 1 1 1 1\n", 4, 1, 0,1,0); check("2 component\n 5 6\n", "revlex 2\n component\n 5 6\n", 2, 1, 1, 1, 0); check("2 3 4\nrevcomponent\n","revlex 2\n 3 4\n revcomponent\n",2, 1, 1,0,0); check("lex 1 component", "lex 1\n component\n", 0, 0, 1, 1, 0); check("lex 1 revcomponent", "lex 1\n revcomponent\n", 1, 0, 1, 0, 0); check("lex 1 revcomponent", "lex 1\n revcomponent\n", 5, 0, 1, 0, 0); check( "schreyer lex 1 1 _revlex revcomponent", "schreyer revlex 1\n 1\n _revlex\n revcomponent\n", 1, 1, 1, 0, 1 ); } mathicgb-master/src/test/MonoMonoid.cpp000077500000000000000000000711231311555162500204700ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/MonoMonoid.hpp" #include "mathicgb/MonoArena.hpp" #include "mathicgb/MathicIO.hpp" #include #include using namespace mgb; // Do all-pairs testing -- see monoidPict.in. Especially see that file before // editing this list of types. typedef ::testing::Types< MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid, MonoMonoid > MonoidTypes; template class Monoids : public ::testing::Test {}; TYPED_TEST_CASE(Monoids, MonoidTypes); // expect(i,j) encodes a matrix with interesting bit patterns that // are supposed to be likely to surface errors in how monomials are // stored inside a vector. uint32 expect(size_t mono, size_t var, size_t varCount) { const auto unique = (static_cast(var + varCount * mono + 1) % 127); while (true) { // 000 if (mono == 0) return 0; --mono; // 100 // 010 // 001 if (mono < varCount) return var == mono ? unique : 0; mono -= varCount; // 000 // 100 // 110 // 111 if (mono < varCount + 1) return var < mono ? unique : 0; mono -= varCount + 1; // 111 // 011 // 001 // 000 if (mono < varCount + 1) return var >= mono ? unique : 0; mono -= varCount + 1; // 101 // 010 if (mono < 4) return (var % 2) == (mono % 2) ? unique : 0; mono -= 4; // 100100 // 010010 // 001001 if (mono < 6) return (var % 3) == (mono % 3) ? unique : 0; mono -= 6; // mix the patterns mono += var % 17; } }; TYPED_TEST(Monoids, VarCount) { typedef TypeParam Monoid; ASSERT_EQ(0, Monoid(0).varCount()); ASSERT_EQ(1000 * 1000, Monoid(1000 * 1000).varCount()); ASSERT_EQ(1, Monoid(1).varCount()); ASSERT_EQ(2, Monoid(2).varCount()); ASSERT_EQ(12, Monoid(12).varCount()); } template void testMonoVector() { typedef typename Monoid::VarIndex VarIndex; Monoid monoid(13); MonoVector v(monoid); MonoVector v2(monoid); ASSERT_EQ(v2.monoid(), monoid); const auto varCount = monoid.varCount(); ASSERT_TRUE(v.empty()); size_t count = 1000; // Not a correctness error, but empty vectors should preferably not // use any memory. ASSERT_EQ(0, v.memoryBytesUsed()); for (size_t i = 0; i < count; ++i) { ASSERT_EQ(i, v.size()); v.push_back(); // push_back, no param ASSERT_GT(v.memoryBytesUsed(), 0u); ASSERT_FALSE(v.empty()); // empty ASSERT_EQ(i + 1, v.size()); // size ASSERT_TRUE(monoid.isIdentity(v.back())); // isIdentity true, back non-const bool allZero = true; for (VarIndex var = 0; var < varCount; ++var) { const auto exponent = expect(i, var, varCount); if (exponent != 0) { allZero = false; monoid.setExponent(var, exponent, v.back()); } } ASSERT_EQ(allZero, monoid.isIdentity(v.back())); // isIdentity false v2.push_back(v.back()); // push_back with param ASSERT_TRUE(monoid.equal(v.back(), v2.back())); } auto it = v.begin(); ASSERT_EQ(it, v.cbegin()); for (size_t i = 0; i < count; ++i, ++it) { typename MonoVector::const_iterator tmp; tmp = it; ASSERT_EQ(tmp, it); ASSERT_TRUE(v.end() != it); for (VarIndex var = 0; var < monoid.varCount(); ++var) { ASSERT_EQ(expect(i, var, varCount), monoid.exponent(*it, var)); } } ASSERT_EQ(v.end(), it); ASSERT_EQ(v.cend(), it); ASSERT_EQ(v, v2); // operator== true monoid.setExponent(0, 1 + monoid.exponent(v2.back(), 0), v2.back()); ASSERT_TRUE(v != v2); // operator!=, true, same length auto& vc = const_cast(v); ASSERT_TRUE(monoid.equal(v.front(), *v2.begin())); // front, non-const ASSERT_TRUE(monoid.equal(vc.front(), *v2.begin())); // front, const ASSERT_TRUE(monoid.equal(vc.back(), v.back())); // back, non-const auto v3(v2); // copy constructor ASSERT_EQ(v3.monoid(), monoid); ASSERT_TRUE(v != v3 && v2 == v3); v2.swap(v); // member swap ASSERT_TRUE(v == v3 && v2 != v3); std::swap(v, v2); // std::swap ASSERT_TRUE(v != v3 && v2 == v3); using std::swap; swap(v, v2); // let compiler decide which swap to use ASSERT_TRUE(v == v3 && v2 != v3); swap(v, v2); // get back to original state ASSERT_TRUE(v != v3 && v2 == v3); ASSERT_FALSE(v3 != v2); // operator!=, false, same length v3.push_back(); ASSERT_TRUE(v3 != v2); // operator!=, true, different length ASSERT_FALSE(v3 == v); v3 = v; // copy assignment ASSERT_EQ(v3.monoid(), monoid); ASSERT_EQ(v3, v); ASSERT_FALSE(v3.empty()); v2 = std::move(v3); // move assignment ASSERT_EQ(v2.monoid(), monoid); ASSERT_EQ(v2, v); ASSERT_TRUE(v3.empty()); ASSERT_FALSE(v2.empty()); auto v4(std::move(v2)); // move constructor ASSERT_EQ(v4.monoid(), monoid); ASSERT_TRUE(v2.empty()); ASSERT_EQ(v4, v); ASSERT_FALSE(v.empty()); v.clear(); ASSERT_TRUE(v.empty()); } TYPED_TEST(Monoids, MonoVector) { typedef TypeParam Monoid; typedef typename Monoid::MonoVector MonoVector; testMonoVector(); } TYPED_TEST(Monoids, MonoArena) { typedef TypeParam Monoid; typedef MonoArena Arena; Monoid monoid(15); Arena a(monoid); a.push_back(); return; testMonoVector>(); } TYPED_TEST(Monoids, ReadWriteMonoid) { typedef TypeParam Monoid; typedef typename Monoid::VarIndex VarIndex; const auto check = []( const char* const inStr, const char* const outStr, const VarIndex varCount, const VarIndex gradingCount ) -> void { for (int i = 0; i < 2; ++i) { const char* str = i == 0 ? inStr : outStr; if (str == 0) continue; std::istringstream inStream(str); Scanner in(inStream); const auto order = MathicIO(). readOrderWithVarCount(Monoid::HasComponent, in); const Monoid monoid(order); const auto constructedOrder = monoid.makeOrder (order.componentsAscendingDesired(), order.schreyering()); std::ostringstream out; MathicIO().writeOrderWithVarCount (constructedOrder, Monoid::HasComponent, out); ASSERT_EQ(outStr, out.str()); ASSERT_EQ(varCount, order.varCount()); ASSERT_EQ(varCount, monoid.varCount()); ASSERT_EQ(varCount, constructedOrder.varCount()); ASSERT_EQ(gradingCount, monoid.gradingCount()); } }; check("0 0\n", "0\nrevlex 0\n", 0, 0); check("1 1\n 2\n", "1\nrevlex 1\n 2\n", 1, 1); check("1 2\n 3\n 4\n", "1\nrevlex 2\n 3\n 4\n", 1, 2); check("2 2\n 3 4\n 5 6\n", "2\nrevlex 2\n 3 4\n 5 6\n", 2, 2); check("4 1\n 1 1 1 1\n", "4\nrevlex 1\n 1 1 1 1\n", 4, 1); check("0 lex 0", "0\nlex 0\n", 0, 0); check("1 lex 1 2", "1\nlex 1\n 2\n", 1, 1); check("1 lex 2 3 4", "1\nlex 2\n 3\n 4\n", 1, 2); check("2 lex 2 3 4 5 6", "2\nlex 2\n 3 4\n 5 6\n", 2, 2); check("4 lex 1 1 1 1 1", "4\nlex 1\n 1 1 1 1\n", 4, 1); if (Monoid::HasComponent) { check("2 2\n component\n 5 6\n", "2\nrevlex 2\n component\n 5 6\n", 2, 2); check ("2 2\n 3 4\n revcomponent\n","2\nrevlex 2\n 3 4\n revcomponent\n", 2, 2); check("0 lex 1 component", "0\nlex 1\n component\n", 0, 1); check("1 lex 1 revcomponent", "1\nlex 1\n revcomponent\n", 1, 1); check("5 lex 1 revcomponent", "5\nlex 1\n revcomponent\n", 5, 1); } } TYPED_TEST(Monoids, MonoPool) { typedef TypeParam Monoid; typedef typename Monoid::VarIndex VarIndex; typedef typename Monoid::Mono Mono; for (int q = 0; q < 2; ++q) { Monoid monoid(13); typename Monoid::MonoPool pool(monoid); const auto varCount = monoid.varCount(); const auto count = 1000; std::vector monos; for (int i = 0; i < count; ++i) { pool.alloc(); pool.free(pool.alloc()); auto m1 = pool.alloc(); ASSERT_TRUE(monoid.isIdentity(*m1)); auto m2 = pool.alloc(); ASSERT_TRUE(monoid.isIdentity(*m2)); for (VarIndex var = 0; var < varCount; ++var) { monoid.setExponent(var, 1, *m1); monoid.setExponent(var, 1, *m2); } if (i > 10) { using std::swap; swap(m2, monos[i - 10]); } monos.emplace_back(std::move(m1)); } // This ensures that we get to each entry in monos exactly once. MATHICGB_ASSERT((count % 17) != 0); int i = 0; do { MATHICGB_ASSERT(!monos[i].isNull()); ASSERT_FALSE(monoid.isIdentity(*monos[i])); pool.free(std::move(monos[i])); ASSERT_TRUE(monos[i].isNull()); pool.free(std::move(monos[i])); ASSERT_TRUE(monos[i].isNull()); i = (i + 17) % count; } while (i != 0); // If the ordering of monomials inside the pool has anything to do with // allocation and deallocation order, then the monomials inside the // pool are at this point all jumbled around. All the entries were also // non-zero before, so we test that new allocations are the identity. for (int i = 0; i < count; ++i) { monos[i] = pool.alloc(); ASSERT_TRUE(monoid.isIdentity(*monos[i])); for (VarIndex var = 0; var < varCount; ++var) monoid.setExponent(var, expect(i, var, varCount), *monos[i]); } for (int i = 0; i < count; ++i) { for (VarIndex var = 0; var < varCount; ++var) { ASSERT_EQ(expect(i, var, varCount), monoid.exponent(*monos[i], var)); } } // everything should be free'd now. Let's do all that again. } } namespace { template typename M::MonoVector parseVector( M& monoid, const char* str, const bool readComponent ) { typename M::MonoVector v(monoid); Scanner in(str); MathicIO().readMonomialVector(readComponent, in, v); return v; } } TYPED_TEST(Monoids, setExponentAndComponent) { typedef TypeParam Monoid; Monoid m(100); const std::string str = Monoid::HasComponent ? "1<0> a<0> z<0> A<0> Z<0> ab<0> a2<0> a2b<0> ab2<0> " "a20b30<0> 1<1> a<2> a2<3> ab<11>\n" : "1 a z A Z ab a2 a2b ab2 a20b30\n"; auto v2 = parseVector(m, str.c_str(), Monoid::HasComponent); std::ostringstream v2Out; MathicIO().writeMonomialVector(v2, Monoid::HasComponent, v2Out); ASSERT_EQ(str, v2Out.str()); decltype(v2) v(m); v.push_back(); // 1 v.push_back(); // a m.setExponent(0, 1, v.back()); v.push_back(); // z m.setExponent(25, 1, v.back()); v.push_back(); // A m.setExponent(26, 1, v.back()); v.push_back(); // Z m.setExponent(51, 1, v.back()); v.push_back(); // ab m.setExponent(0, 1, v.back()); m.setExponent(1, 1, v.back()); v.push_back(); // a2 m.setExponent(0, 2, v.back()); v.push_back(); // a2b m.setExponent(0, 2, v.back()); m.setExponent(1, 1, v.back()); v.push_back(); // ab2 m.setExponent(0, 1, v.back()); m.setExponent(1, 2, v.back()); v.push_back(); // a20b30 m.setExponent(0, 20, v.back()); m.setExponent(1, 30, v.back()); if (Monoid::HasComponent) { v.push_back(); // 1<1> m.setComponent(1, v.back()); v.push_back(); // a<2> m.setComponent(2, v.back()); m.setExponent(0, 1, v.back()); v.push_back(); // a2<3> m.setComponent(3, v.back()); m.setExponent(0, 2, v.back()); v.push_back(); // ab<11> m.setComponent(11, v.back()); m.setExponent(0, 1, v.back()); m.setExponent(1, 1, v.back()); } std::ostringstream vOut; MathicIO().writeMonomialVector(v, Monoid::HasComponent, vOut); ASSERT_EQ(str, vOut.str()); ASSERT_EQ(v, v2); } TYPED_TEST(Monoids, MultiplyDivide) { typedef TypeParam Monoid; Monoid m(49); typename Monoid::MonoPool pool(m); auto monoOwner = pool.alloc(); auto mono = *monoOwner; auto check = [&](const char* const str, const bool component) -> void { if (component && !Monoid::HasComponent) return; auto v = parseVector(m, str, component); MATHICGB_ASSERT(v.size() == 3); const auto& a = v.front(); const auto& b = *++v.begin(); const auto& c = v.back(); ASSERT_EQ(m.hashOfProduct(a, b), m.hash(c)); ASSERT_EQ(m.hashOfProduct(a, b), m.hashOfProduct(b, a)); // isProductOf ASSERT_TRUE(m.isProductOf(a, b, c)); ASSERT_TRUE(m.isProductOfHintTrue(a, b, c)); ASSERT_TRUE(m.isTwoProductsOfHintTrue(a, a, b, c, c)); // a*b == c using multiply m.multiply(a, b, mono); ASSERT_TRUE(m.equal(c, mono)); ASSERT_TRUE(m.compare(c, mono) == Monoid::EqualTo); ASSERT_EQ(m.hash(c), m.hash(mono)); // c/a == b using divide m.divide(a, c, mono); ASSERT_TRUE(m.equal(b, mono)); ASSERT_TRUE(m.compare(b, mono) == Monoid::EqualTo); ASSERT_EQ(m.hash(b), m.hash(mono)); // c/b == a using divideInPlace m.copy(c, mono); m.divideInPlace(b, mono); ASSERT_TRUE(m.equal(a, mono)); ASSERT_TRUE(m.compare(a, mono) == Monoid::EqualTo); ASSERT_EQ(m.hash(a), m.hash(mono)); // a*b == c using multiplyInPlace m.copy(a, mono); m.multiplyInPlace(b, mono); ASSERT_TRUE(m.equal(c, mono)); ASSERT_TRUE(m.compare(c, mono) == Monoid::EqualTo); ASSERT_EQ(m.hash(c), m.hash(mono)); // divides, check properties that mono=a*b should have ASSERT_TRUE(m.divides(mono, c)); ASSERT_TRUE(m.divides(c, mono)); ASSERT_TRUE(m.divides(a, mono)); ASSERT_TRUE(m.divides(b, mono)); // divides, general ASSERT_TRUE(m.divides(m, mono, c)); ASSERT_TRUE(m.divides(m, c, mono)); ASSERT_TRUE(m.divides(m, a, mono)); ASSERT_TRUE(m.divides(m, b, mono)); if (!m.isIdentity(a)) { ASSERT_TRUE(m.lessThan(b, mono)); ASSERT_FALSE(m.lessThan(mono, b)); ASSERT_TRUE(m.compare(mono, b) == Monoid::GreaterThan); ASSERT_FALSE(m.divides(mono, b)); ASSERT_FALSE(m.divides(m, mono, b)); ASSERT_FALSE(m.isProductOf(a, c, b)); ASSERT_FALSE(m.isProductOfHintTrue(a, c, b)); ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, c, a, b, b)); ASSERT_FALSE(m.isTwoProductsOfHintTrue(b, c, a, c, b)); ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, b, a, b, c)); } else { ASSERT_TRUE(m.equal(b, mono)); ASSERT_TRUE(m.compare(b, mono) == Monoid::EqualTo); ASSERT_TRUE(m.divides(mono, b)); ASSERT_TRUE(m.divides(m, mono, b)); } if (!m.isIdentity(b)) { ASSERT_TRUE(m.lessThan(a, mono)); ASSERT_FALSE(m.lessThan(mono, a)); ASSERT_TRUE(m.compare(mono, a) == Monoid::GreaterThan); ASSERT_FALSE(m.divides(mono, a)); ASSERT_FALSE(m.divides(m, mono, a)); ASSERT_FALSE(m.isProductOf(c, b, a)); ASSERT_FALSE(m.isProductOfHintTrue(b, c, a)); ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, c, b, a, a)); ASSERT_FALSE(m.isTwoProductsOfHintTrue(a, c, b, c, a)); ASSERT_FALSE(m.isTwoProductsOfHintTrue(c, a, b, a, c)); } else { ASSERT_TRUE(m.equal(a, mono)); ASSERT_TRUE(m.compare(a, mono) == Monoid::EqualTo); ASSERT_TRUE(m.divides(m, mono, a)); } // Check that aliased parameters work. m.multiply(mono, mono, mono); m.divide(mono, mono, mono); MATHICGB_ASSERT(m.isIdentity(mono)); // Check that negative exponents work. if (Monoid::HasComponent && m.component(a) != m.component(b)) return; m.divideToNegative(a, b, mono); m.multiply(a, mono, mono); ASSERT_TRUE(m.equal(mono, b)); m.divideToNegative(b, a, mono); m.multiply(b, mono, mono); ASSERT_TRUE(m.equal(mono, a)); }; check("1 1 1", false); check("a<5> 1<0> a<5>", true); check("1 Vx Vx", false); check("aV bx abxV", false); check("a a2 a3", false); check("V<2> V2<0> V3<2>", true); check("arlgh svug arlg2hsvu", false); check ("abcdefghiV<7> ab2c3d4e5f6g7h8i9V11<0> a2b3c4d5e6f7g8h9i10V12<7>", true); } TYPED_TEST(Monoids, LcmColon) { typedef TypeParam Monoid; Monoid mNonConst(49); auto& m = mNonConst; typename Monoid::MonoPool pool(m); auto monoOwner = pool.alloc(); auto mono = *monoOwner; auto mono2Owner = pool.alloc(); auto mono2 = *mono2Owner; auto check = [&](const char* const str, const bool component) -> void { if (component && !Monoid::HasComponent) return; auto v = parseVector(m, str, component); MATHICGB_ASSERT(v.size() == 3); const auto& a = v.front(); const auto& b = *++v.begin(); const auto& lcm = v.back(); // isLcm (+general) ASSERT_TRUE(m.isLcm(a, b, lcm)); ASSERT_TRUE(m.isLcm(m, a, m, b, lcm)); m.copy(lcm, mono); m.setExponent(1, m.exponent(mono, 1) + 1, mono); ASSERT_FALSE(m.isLcm(a, b, mono)); ASSERT_FALSE(m.isLcm(m, a, m, b, mono)); // dividesLcm ASSERT_TRUE(m.dividesLcm(lcm, a, b)); ASSERT_FALSE(m.dividesLcm(mono, a, b)); ASSERT_TRUE(m.dividesLcm(a, a, a)); ASSERT_TRUE(m.dividesLcm(a, a, b)); ASSERT_TRUE(m.dividesLcm(b, b, b)); ASSERT_TRUE(m.dividesLcm(b, b, a)); // dividesLcm, general ASSERT_TRUE(m.dividesLcm(m, lcm, m, a, b)); ASSERT_FALSE(m.dividesLcm(m, mono, m, a, b)); ASSERT_TRUE(m.dividesLcm(m, a, m, a, a)); ASSERT_TRUE(m.dividesLcm(m, a, m, a, b)); ASSERT_TRUE(m.dividesLcm(m, b, m, b, b)); ASSERT_TRUE(m.dividesLcm(m, b, m, b, a)); // lcm(a, b) m.lcm(a, b, mono); ASSERT_TRUE(m.equal(mono, lcm)); ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo); ASSERT_EQ(m.hash(lcm), m.hash(mono)); // lcm(b, a), general m.lcm(m, b, m, a, mono); ASSERT_TRUE(m.equal(mono, lcm)); ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo); ASSERT_EQ(m.hash(lcm), m.hash(mono)); // colons m.colons(a, b, mono, mono2); m.multiply(b, mono, mono); m.multiply(a, mono2, mono2); ASSERT_TRUE(m.equal(mono, lcm)); ASSERT_TRUE(m.compare(mono, lcm) == Monoid::EqualTo); ASSERT_TRUE(m.equal(mono2, lcm)); ASSERT_TRUE(m.compare(mono2, lcm) == Monoid::EqualTo); }; check("1 1 1", false); check("a<2> 1<2> a<2>", true); check("1 Vx Vx", false); check("aV bx abxV", false); check("a a2 a2", false); check("V<3> V2<3> V2<3>", true); check("arlgh svug arlghsvu", false); check("a6b7c8d9efghiV ab2c3d4e5f6g7h8i9V11 a6b7c8d9e5f6g7h8i9V11", false); } TYPED_TEST(Monoids, Order) { typedef TypeParam Monoid; typedef typename Monoid::Order Order; typedef typename Monoid::Exponent Exponent; typedef typename Monoid::ConstMonoRef ConstMonoRef; auto check = []( const Monoid& m, const char* const sorted ) -> void { auto toStr = [&](ConstMonoRef mono) { std::ostringstream out; MathicIO().writeMonomial(m, false, mono, out); return out.str(); }; auto v = parseVector(m, sorted, false); for (auto greater = v.begin(); greater != v.end(); ++greater) { ASSERT_EQ(m.compare(*greater, *greater), Monoid::EqualTo); ASSERT_TRUE(m.equal(*greater, *greater)); ASSERT_FALSE(m.lessThan(*greater, *greater)); for (auto lesser = v.begin(); lesser != greater; ++lesser) { ASSERT_FALSE(m.equal(*lesser, *greater)); ASSERT_TRUE(m.lessThan(*lesser, *greater)) << "String = " << sorted << '\n' << "*lesser = " << toStr(*lesser) << '\n' << "*greater = " << toStr(*greater) << '\n'; ASSERT_FALSE(m.lessThan(*greater, *lesser)); ASSERT_EQ(m.compare(*lesser, *greater), Monoid::LessThan); ASSERT_EQ(m.compare(*greater, *lesser), Monoid::GreaterThan); } } }; const auto sortedTotalDegreeRevLex = "1 Z A z c b a c2 bc ac b2 ab a2 c3 abc b3 a3"; check(Monoid(52), sortedTotalDegreeRevLex); check( Monoid( Order(52, std::vector(52, 1), Order::RevLexBaseOrderFromRight) ), sortedTotalDegreeRevLex ); check( Monoid( Order(52, std::vector(52, 7), Order::RevLexBaseOrderFromRight) ), sortedTotalDegreeRevLex ); std::vector revLexGradings(52, 1); for (size_t grading = 51; grading != static_cast(-1); --grading) for (size_t var = 0; var < 52; ++var) revLexGradings.push_back(var == grading ? -1 : 0); check( Monoid( Order(52, std::vector(revLexGradings), Order::RevLexBaseOrderFromRight) ), sortedTotalDegreeRevLex ); check( Monoid( Order(52, std::move(revLexGradings), Order::LexBaseOrderFromRight) ), sortedTotalDegreeRevLex ); Exponent dupGradingsArray[] = { 5, 2, 3, 10, 4, 6, // duplicate, just multiplied by 2 -6, 9, 4, -6, 9, 4, -6, 9, 4, -6, 9, 4, -6, 9, 4 }; std::vector dupGradings( dupGradingsArray, dupGradingsArray + sizeof(dupGradingsArray)/sizeof(*dupGradingsArray) ); // b: 2 9 // c: 3 4 // a: 5 -7 // bc: 5 20 // c2: 6 8 // b3: 6 27 // bc3: 11 21 // ab3: 11 21 const auto sortedDupGradingsRevLex = "1 b c a bc c2 b3 bc3 ab3"; check( Monoid(Order(3, std::move(dupGradings), Order::RevLexBaseOrderFromRight)), sortedDupGradingsRevLex ); Exponent lexGradingsArray[] = { 0, 0, 1, 0, 1, 0, 1, 0, 0 }; std::vector lexGradings( lexGradingsArray, lexGradingsArray + sizeof(lexGradingsArray) / sizeof(*lexGradingsArray) ); const auto sortedLexFromRight = "1 a a2 a3 b ab a2b b2 ab2 b3 c ac bc abc c2 ac2 bc2 c3"; auto lexGradingsCheck = [&](typename Order::BaseOrder baseOrder) { check( Monoid(Order(3, std::vector(lexGradings), baseOrder)), sortedLexFromRight ); }; lexGradingsCheck(Order::LexBaseOrderFromRight); lexGradingsCheck(Order::RevLexBaseOrderFromRight); lexGradingsCheck(Order::LexBaseOrderFromLeft); lexGradingsCheck(Order::RevLexBaseOrderFromLeft); check( Monoid(Order(3, std::vector(), Order::LexBaseOrderFromRight)), sortedLexFromRight ); const auto sortedLexFromLeft = "1 c c2 c3 b cb bc2 b2 b2c b3 a ac ab abc a2 a2c a2b a3"; check( Monoid(Order(3, std::vector(), Order::LexBaseOrderFromLeft)), sortedLexFromLeft ); } TYPED_TEST(Monoids, RelativelyPrime) { typedef TypeParam Monoid; Monoid m(49); typename Monoid::MonoPool pool(m); auto mono = pool.alloc(); auto mono2 = pool.alloc(); auto check = [&](const char* str, bool relativelyPrime) -> void { auto v = parseVector(m, str, false); MATHICGB_ASSERT(v.size() == 2); ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.front(), v.back())); ASSERT_EQ(relativelyPrime, m.relativelyPrime(v.back(), v.front())); }; check("1 1", true); check("1 abcdefgh", true); check("abc defgh", true); check("bdfh aceg", true); check("bdefh aceg", false); check("abcdefgh abcdefgh", false); check("fgh abcdef", false); } TYPED_TEST(Monoids, SetExponents) { typedef TypeParam Monoid; typedef typename Monoid::VarIndex VarIndex; typedef typename Monoid::MonoVector MonoVector; Monoid m(5); MonoVector v(m); v.push_back(); typename Monoid::Exponent exponents[] = {1, 2, 3, 4, 5}; m.setExternalExponents(exponents, v.back()); for (VarIndex var = 0; var < m.varCount(); ++var) { ASSERT_EQ(exponents[var], m.externalExponent(v.back(), var)); } } TYPED_TEST(Monoids, HasAmpleCapacityTotalDegree) { typedef TypeParam Monoid; typedef typename Monoid::Order Order; typedef typename Monoid::Exponent Exponent; typedef typename Monoid::VarIndex VarIndex; for (VarIndex varCount = 1; varCount < 33; ++varCount) { Monoid monoidTotalDegree(varCount); std::vector ones(varCount, 1); Monoid monoidTotalDegreeImplicit (Order(varCount, std::move(ones), Order::RevLexBaseOrderFromRight)); std::vector mostlyOnes(varCount, 1); mostlyOnes[0] = 7; Monoid monoidGeneral( Order(varCount, std::move(mostlyOnes), Order::RevLexBaseOrderFromRight) ); Monoid* monoids[] = { &monoidTotalDegree, &monoidTotalDegreeImplicit, &monoidGeneral }; for (int j = 0; j < 3; ++j) { auto& m = *monoids[j]; const auto firstDeg = (j == 2 ? 7 : 1); ASSERT_EQ(varCount, m.varCount()); typename Monoid::MonoPool p(m); auto monoOwner = p.alloc(); auto mono = *monoOwner; const auto last = m.varCount() - 1; const auto max = std::numeric_limits::max() / 2; // pure power, first variable m.setIdentity(mono); m.setExponent(0, max / firstDeg, mono); ASSERT_TRUE(m.hasAmpleCapacity(mono)); m.setExponent(0, max / firstDeg + 1, mono); ASSERT_FALSE(m.hasAmpleCapacity(mono)); if (varCount == 1) continue; // pure power, last variable m.setIdentity(mono); m.setExponent(last, max, mono); ASSERT_TRUE(m.hasAmpleCapacity(mono)); m.setExponent(last, max + 1, mono); ASSERT_FALSE(m.hasAmpleCapacity(mono)); // no exponent is too high but the degree is m.setIdentity(mono); m.setExponent(0, 12, mono); m.setExponent(last, max - 12 * firstDeg, mono); ASSERT_TRUE(m.hasAmpleCapacity(mono)); m.setExponent(0, 13, mono); ASSERT_FALSE(m.hasAmpleCapacity(mono)); } } } TYPED_TEST(Monoids, CopyEqualConversion) { typedef TypeParam Monoid; typedef typename Monoid::Order Order; typedef typename Monoid::Exponent Exponent; typedef typename Monoid::VarIndex VarIndex; static const bool HasComponent = Monoid::HasComponent; typedef MonoMonoid MonoidNone; typedef MonoMonoid MonoidAll; for (VarIndex varCount = 1; varCount < 33; ++varCount) { const Order order( varCount, std::vector(varCount, 1), Order::RevLexBaseOrderFromRight ); MonoidNone none(order); Monoid some(Monoid::create(none)); MonoidAll all(MonoidAll::create(some)); auto none1Owner = none.alloc(); auto none2Owner = none.alloc(); auto none3Owner = none.alloc(); auto some1Owner = some.alloc(); auto some2Owner = some.alloc(); auto some3Owner = some.alloc(); auto all1Owner = all.alloc(); auto all2Owner = all.alloc(); auto all3Owner = all.alloc(); auto none1 = *none1Owner; auto none2 = *none2Owner; auto none3 = *none3Owner; auto some1 = *some1Owner; auto some2 = *some2Owner; auto some3 = *some3Owner; auto all1 = *all1Owner; auto all2 = *all2Owner; auto all3 = *all3Owner; none.setExponent(0, 1, none1); none.setExponent(varCount / 2, 2, none1); none.setExponent(varCount - 1, 3, none1); none.copy(none1, none2); none.setExponent(0, 4, none2); some.setExponent(0, 1, some1); some.setExponent(varCount / 2, 2, some1); some.setExponent(varCount - 1, 3, some1); some.copy(some1, some2); some.setExponent(0, 4, some2); all.setExponent(0, 1, all1); all.setExponent(varCount / 2, 2, all1); all.setExponent(varCount - 1, 3, all1); all.copy(all1, all2); all.setExponent(0, 4, all2); // compare on none ASSERT_TRUE(none.equal(none, none1, none1)); ASSERT_TRUE(none.equal(some, some1, none1)); ASSERT_TRUE(none.equal(all, all1, none1)); ASSERT_FALSE(none.equal(none, none1, none2)); ASSERT_FALSE(none.equal(some, some1, none2)); ASSERT_FALSE(none.equal(all, all1, none2)); // compare on some ASSERT_TRUE(some.equal(none, none1, some1)); ASSERT_TRUE(some.equal(some, some1, some1)); ASSERT_TRUE(some.equal(all, all1, some1)); ASSERT_FALSE(some.equal(none, none1, some2)); ASSERT_FALSE(some.equal(some, some1, some2)); ASSERT_FALSE(some.equal(all, all1, some2)); // compare on all ASSERT_TRUE(all.equal(none, none1, all1)); ASSERT_TRUE(all.equal(some, some1, all1)); ASSERT_TRUE(all.equal(all, all1, all1)); ASSERT_FALSE(all.equal(none, none1, all2)); ASSERT_FALSE(all.equal(some, some1, all2)); ASSERT_FALSE(all.equal(all, all1, all2)); // convert some->none none.copy(some, some1, none3); ASSERT_TRUE(none.equal(none1, none3)); ASSERT_FALSE(none.equal(none2, none3)); none.copy(some, some2, none3); ASSERT_FALSE(none.equal(none1, none3)); ASSERT_TRUE(none.equal(none2, none3)); /// convert some->all all.copy(some, some1, all3); ASSERT_TRUE(all.equal(all1, all3)); ASSERT_FALSE(all.equal(all2, all3)); all.copy(some, some2, all3); ASSERT_FALSE(all.equal(all1, all3)); ASSERT_TRUE(all.equal(all2, all3)); // convert none->some some.copy(none, none1, some3); ASSERT_TRUE(some.equal(some1, some3)); ASSERT_FALSE(some.equal(some2, some3)); some.copy(none, none2, some3); ASSERT_FALSE(some.equal(some1, some3)); ASSERT_TRUE(some.equal(some2, some3)); // convert Y->some some.copy(none, none1, some3); ASSERT_TRUE(some.equal(some1, some3)); ASSERT_FALSE(some.equal(some2, some3)); some.copy(none, none2, some3); ASSERT_FALSE(some.equal(some1, some3)); ASSERT_TRUE(some.equal(some2, some3)); } } mathicgb-master/src/test/PrimeField.cpp000077500000000000000000000200601311555162500204240ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/PrimeField.hpp" #include #include using namespace mgb; namespace { template std::string toString(T&& t) { std::ostringstream out; out << static_cast(t.value()); return out.str(); } } TEST(PrimeField, Charac) { const PrimeField pf(11); ASSERT_EQ(pf.charac(), 11); } TEST(PrimeField, OneZero) { const PrimeField pfChar(11); ASSERT_EQ("0", toString(pfChar.zero())); ASSERT_EQ("1", toString(pfChar.one())); ASSERT_TRUE(pfChar.isOne(pfChar.one())); ASSERT_FALSE(pfChar.isOne(pfChar.zero())); ASSERT_FALSE(pfChar.isZero(pfChar.one())); ASSERT_TRUE(pfChar.isZero(pfChar.zero())); const PrimeField pfLong(11); ASSERT_EQ("0", toString(pfLong.zero())); ASSERT_EQ("1", toString(pfLong.one())); ASSERT_TRUE(pfLong.isOne(pfLong.one())); ASSERT_FALSE(pfLong.isOne(pfLong.zero())); ASSERT_FALSE(pfLong.isZero(pfLong.one())); ASSERT_TRUE(pfLong.isZero(pfLong.zero())); } TEST(PrimeField, toElement) { const auto max32BitUnsignedPrime = 4294967291u; const PrimeField pf(max32BitUnsignedPrime); // Same number of bits (32) ASSERT_EQ("0", toString(pf.toElement(0))); ASSERT_EQ("1", toString(pf.toElement(1))); ASSERT_EQ("4294967290", toString(pf.toElement(-1))); ASSERT_EQ("0", toString(pf.toElement(max32BitUnsignedPrime))); ASSERT_EQ("1", toString(pf.toElement(max32BitUnsignedPrime + 1u))); ASSERT_EQ("4294967290", toString(pf.toElement(max32BitUnsignedPrime - 1u))); ASSERT_EQ("4", toString(pf.toElement(std::numeric_limits::max()))); ASSERT_EQ("2147483643", toString(pf.toElement(std::numeric_limits::min()))); // Fewer number of bits (8) ASSERT_EQ("127", toString(pf.toElement(std::numeric_limits::max()))); ASSERT_EQ("4294967163", toString(pf.toElement(std::numeric_limits::min()))); ASSERT_EQ("255", toString(pf.toElement(std::numeric_limits::max()))); ASSERT_EQ("0", toString(pf.toElement(std::numeric_limits::min()))); // More bits (64) ASSERT_EQ("24", toString(pf.toElement(std::numeric_limits::max()))); ASSERT_EQ("2147483657", toString(pf.toElement(std::numeric_limits::max()))); ASSERT_EQ("2147483633", toString(pf.toElement(std::numeric_limits::min()))); } TEST(PrimeField, Sum) { const PrimeField pf2(2); ASSERT_EQ(pf2.zero(), pf2.sum(pf2.zero(), pf2.zero())); ASSERT_EQ(pf2.one(), pf2.sum(pf2.one(), pf2.zero())); ASSERT_EQ(pf2.one(), pf2.sum(pf2.zero(), pf2.one())); ASSERT_EQ(pf2.zero(), pf2.sum(pf2.one(), pf2.one())); const PrimeField pf251(251); ASSERT_EQ(pf251.one(), pf251.sum(pf251.zero(), pf251.one())); ASSERT_EQ(pf251.toElement(-3), pf251.sum(pf251.toElement(-1), pf251.toElement(-2))); const PrimeField pf101(101); ASSERT_EQ(pf101.toElement(100), pf101.sum(pf101.toElement(40), pf101.toElement(60))); ASSERT_EQ(pf101.toElement(9), pf101.sum(pf101.toElement(50), pf101.toElement(60))); } TEST(PrimeField, Negative) { const PrimeField pf2(2); ASSERT_EQ(pf2.zero(), pf2.negative(pf2.zero())); ASSERT_EQ(pf2.one(), pf2.negative(pf2.one())); ASSERT_EQ(pf2.one(), pf2.negativeNonZero(pf2.one())); const PrimeField pf251(251); ASSERT_EQ(pf251.zero(), pf251.negative(pf251.zero())); ASSERT_EQ(pf251.toElement(100), pf251.negative(pf251.toElement(151))); ASSERT_EQ(pf251.toElement(100), pf251.negativeNonZero(pf251.toElement(151))); } TEST(PrimeField, Difference) { const PrimeField pf2(2); ASSERT_EQ(pf2.zero(), pf2.difference(pf2.zero(), pf2.zero())); ASSERT_EQ(pf2.one(), pf2.difference(pf2.one(), pf2.zero())); ASSERT_EQ(pf2.one(), pf2.difference(pf2.zero(), pf2.one())); ASSERT_EQ(pf2.zero(), pf2.difference(pf2.one(), pf2.one())); const PrimeField pf251(251); ASSERT_EQ(pf251.one(), pf251.difference(pf251.one(), pf251.zero())); ASSERT_EQ(pf251.toElement(-3), pf251.difference(pf251.toElement(1), pf251.toElement(4))); const PrimeField pf101(101); ASSERT_EQ(pf101.toElement(20), pf101.difference(pf101.toElement(60), pf101.toElement(40))); ASSERT_EQ(pf101.toElement(-20), pf101.difference(pf101.toElement(40), pf101.toElement(60))); } TEST(PrimeField, Product) { const PrimeField pf2(2); ASSERT_EQ(pf2.zero(), pf2.product(pf2.zero(), pf2.zero())); ASSERT_EQ(pf2.zero(), pf2.product(pf2.one(), pf2.zero())); ASSERT_EQ(pf2.zero(), pf2.product(pf2.zero(), pf2.one())); ASSERT_EQ(pf2.one(), pf2.product(pf2.one(), pf2.one())); const PrimeField pf251(251); ASSERT_EQ(pf251.zero(), pf251.product(pf251.one(), pf251.zero())); ASSERT_EQ(pf251.one(), pf251.product(pf251.one(), pf251.one())); ASSERT_EQ(pf251.one(), pf251.product(pf251.toElement(-1), pf251.toElement(-1))); ASSERT_EQ(pf251.one(), pf251.product(pf251.toElement(2), pf251.toElement(126))); const PrimeField pf101(101); ASSERT_EQ(pf101.toElement(20), pf101.product(pf101.toElement(5), pf101.toElement(4))); ASSERT_EQ(pf101.toElement(-20), pf101.product(pf101.toElement(-2), pf101.toElement(10))); const PrimeField pf16(65521); ASSERT_EQ(pf16.toElement(-20), pf16.product(pf16.toElement(-2), pf16.toElement(10))); const PrimeField pf32(4294967291u); ASSERT_EQ(pf32.toElement(-20), pf32.product(pf32.toElement(-2), pf32.toElement(10))); } TEST(PrimeField, Inverse) { const PrimeField pf2(2); ASSERT_EQ(pf2.one(), pf2.inverse(pf2.one())); const PrimeField pf251(251); ASSERT_EQ(pf251.one(), pf2.inverse(pf251.one())); ASSERT_EQ(pf251.toElement(-1), pf251.inverse(pf251.toElement(-1))); ASSERT_EQ(pf251.toElement(235), pf251.inverse(pf251.toElement(47))); const PrimeField pf16(65521); ASSERT_EQ(pf16.one(), pf16.inverse(pf16.one())); ASSERT_EQ(pf16.toElement(-1), pf16.inverse(pf16.toElement(-1))); ASSERT_EQ(pf16.toElement(43216), pf16.inverse(pf16.toElement(47))); const PrimeField pf32(4294967291u); ASSERT_EQ(pf32.one(), pf32.inverse(pf32.one())); ASSERT_EQ(pf32.toElement(-1), pf32.inverse(pf32.toElement(-1))); ASSERT_EQ(pf32.toElement(3015615332u), pf32.inverse(pf32.toElement(47))); } TEST(PrimeField, Quotient) { const PrimeField pf2(2); ASSERT_EQ(pf2.one(), pf2.quotient(pf2.one(), pf2.one())); ASSERT_EQ(pf2.zero(), pf2.quotient(pf2.zero(), pf2.one())); const PrimeField pf251(251); ASSERT_EQ(pf251.one(), pf2.quotient(pf251.one(), pf251.one())); ASSERT_EQ (pf251.toElement(-1), pf251.quotient(pf251.one(), pf251.toElement(-1))); ASSERT_EQ (pf251.toElement(-1), pf251.quotient(pf251.toElement(-1), pf251.one())); ASSERT_EQ( pf251.one(), pf251.quotient(pf251.toElement(-1), pf251.toElement(-1)) ); ASSERT_EQ( pf251.toElement(203), pf251.quotient(pf251.toElement(3), pf251.toElement(47)) ); const PrimeField pf16(65521); ASSERT_EQ( pf16.toElement(20911), pf16.quotient(pf16.toElement(2), pf16.toElement(47)) ); const PrimeField pf32(4294967291u); ASSERT_EQ( pf32.toElement(3015615332u), pf32.quotient(pf32.toElement(1), pf32.toElement(47)) ); } TEST(PrimeField, PlusOne) { const PrimeField pf2(2); ASSERT_EQ(pf2.zero(), pf2.plusOne(pf2.one())); ASSERT_EQ(pf2.one(), pf2.plusOne(pf2.zero())); const PrimeField pf251(251); ASSERT_EQ(pf251.one(), pf251.plusOne(pf251.zero())); ASSERT_EQ(pf251.zero(), pf251.plusOne(pf251.toElement(-1))); ASSERT_EQ(pf251.toElement(250), pf251.plusOne(pf251.toElement(249))); const PrimeField pf16(65521); ASSERT_EQ(pf16.toElement(20911), pf16.plusOne(pf16.toElement(20910))); const PrimeField pf32(4294967291u); ASSERT_EQ (pf32.toElement(3015615332u), pf32.plusOne(pf32.toElement(3015615331u))); } mathicgb-master/src/test/QuadMatrixBuilder.cpp000077500000000000000000000205131311555162500217750ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/QuadMatrixBuilder.hpp" #include "mathicgb/Poly.hpp" #include "mathicgb/PolyRing.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/Basis.hpp" #include "mathicgb/QuadMatrix.hpp" #include "mathicgb/MathicIO.hpp" #include using namespace mgb; namespace { std::string monToStr(const PolyRing& ring, ConstMonomial a) { std::ostringstream out; ring.monomialDisplay(out, a, false, true); return out.str(); } template std::string monoToStr( const Monoid& monoid, typename Monoid::ConstMonoRef a ) { std::ostringstream out; MathicIO().writeMonomial(monoid, false, a, out); return out.str(); } void createColumns(const char* left, const char* right, QuadMatrixBuilder& b) { const PolyRing& ring = b.ring(); { std::istringstream in(left); Scanner scanner(in); auto p = MathicIO<>().readPolyDoNotOrder(ring, true, scanner); size_t colCount = 0; for (auto it = p.begin(); it != p.end(); ++it) { QuadMatrixBuilder::LeftRightColIndex lrCol = b.createColumnLeft(it.mono()).first; ASSERT_TRUE(lrCol.left()); ASSERT_FALSE(lrCol.right()); auto col = lrCol.leftIndex(); ASSERT_EQ(col, lrCol.index()); ASSERT_EQ(colCount, col); ++colCount; } } { std::istringstream in(right); Scanner scanner(in); auto p = MathicIO<>().readPolyDoNotOrder(ring, true, scanner); size_t colCount = 0; for (auto it = p.begin(); it != p.end(); ++it) { QuadMatrixBuilder::LeftRightColIndex lrCol = b.createColumnRight(it.mono()).first; ASSERT_TRUE(lrCol.right()); ASSERT_FALSE(lrCol.left()); auto col = lrCol.rightIndex(); ASSERT_EQ(col, lrCol.index()); ASSERT_EQ(colCount, col); ++colCount; } } } } TEST(QuadMatrixBuilder, Empty) { // test a builder with no rows and no columns PolyRing ring(2, PolyRing::Monoid(0)); QuadMatrixBuilder::Map map(ring); QuadMatrixBuilder::Monomials monoLeft; QuadMatrixBuilder::Monomials monoRight; QuadMatrixBuilder b(ring, map, monoLeft, monoRight); const char* matrixStr = "Left columns:\n" "Right columns:\n" "matrix with no rows | matrix with no rows\n" " | \n" "matrix with no rows | matrix with no rows\n"; auto matrix = b.buildMatrixAndClear(); matrix.leftColumnMonomials = monoLeft; matrix.rightColumnMonomials = monoRight; ASSERT_EQ(matrixStr, matrix.toString()); } TEST(QuadMatrixBuilder, Construction) { std::unique_ptr ring(ringFromString("32003 6 1\n1 1 1 1 1 1")); QuadMatrixBuilder::Map map(*ring); QuadMatrixBuilder::Monomials monoLeft; QuadMatrixBuilder::Monomials monoRight; QuadMatrixBuilder b(*ring, map, monoLeft, monoRight); createColumns("a<1>+<0>", "bc<0>+b<0>+c<0>", b); // top row: nothing, nothing b.rowDoneTopLeftAndRight(); // top row: 0#1 1#2, 2#3 b.appendEntryTopLeft(0, 1); b.appendEntryTopLeft(1, 2); b.appendEntryTopRight(2, 3); b.rowDoneTopLeftAndRight(); // bottom row: 1#4, nothing b.appendEntryBottomLeft(1,4); b.rowDoneBottomLeftAndRight(); // bottom row: nothing, 0#5 b.appendEntryBottomRight(0,5); b.rowDoneBottomLeftAndRight(); // bottom row: nothing, nothing b.rowDoneBottomLeftAndRight(); const char* matrixStr = "Left columns: a 1\n" "Right columns: bc b c\n" "0: | 0: \n" "1: 0#1 1#2 | 1: 2#3\n" " | \n" "0: 1#4 | 0: \n" "1: | 1: 0#5\n" "2: | 2: \n"; auto matrix = b.buildMatrixAndClear(); matrix.leftColumnMonomials = monoLeft; matrix.rightColumnMonomials = monoRight; ASSERT_EQ(matrixStr, matrix.toString()); } TEST(QuadMatrixBuilder, ColumnQuery) { std::unique_ptr ring(ringFromString("32003 6 1\n1 1 1 1 1 1")); QuadMatrixBuilder::Map map(*ring); QuadMatrixBuilder::Monomials monoLeft; QuadMatrixBuilder::Monomials monoRight; QuadMatrixBuilder b(*ring, map, monoLeft, monoRight); createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b); // coefficient 1X=left, 2X=right, 30=not there, % 10 = column index std::istringstream in ("10a<1>+11<0>+20b<0>+21c<0>+22bc<0>+30ab<0>+30e<0>+10a<1>"); Scanner scanner(in); auto p = MathicIO<>().readPolyDoNotOrder(b.ring(), true, scanner); for (auto it = p.begin(); it != p.end(); ++it) { const QuadMatrixBuilder::LeftRightColIndex* col = MonomialMap::Reader(map). find(it.mono()).first; if (it.coef() / 10 == 3) ASSERT_EQ(col, static_cast(0)); else { ASSERT_TRUE(col != static_cast(0)); ASSERT_EQ(it.coef() % 10, col->index()); if (it.coef() / 10 == 2) ASSERT_TRUE(col->right()); else ASSERT_TRUE(col->left()); } } } TEST(QuadMatrixBuilder, SortColumns) { // construct builder and reverse lex order std::unique_ptr ring(ringFromString("32003 6 1\n1 1 1 1 1 1")); Basis basis(*ring); // one row top, no rows bottom, no columns { QuadMatrixBuilder::Map map(*ring); QuadMatrixBuilder::Monomials monoLeft; QuadMatrixBuilder::Monomials monoRight; QuadMatrixBuilder b(*ring, map, monoLeft, monoRight); b.rowDoneTopLeftAndRight(); auto matrix = b.buildMatrixAndClear(); matrix.sortColumnsLeftRightParallel(); const char* matrixStr = "Left columns:\n" "Right columns:\n" "0: | 0: \n" " | \n" "matrix with no rows | matrix with no rows\n"; ASSERT_EQ(matrixStr, matrix.toString()); } { QuadMatrixBuilder::Map map(*ring); QuadMatrixBuilder::Monomials monoLeft; QuadMatrixBuilder::Monomials monoRight; QuadMatrixBuilder b(*ring, map, monoLeft, monoRight); createColumns("<0>+a<0>", "b<0>+bcd<0>+bc<0>", b); b.appendEntryTopLeft(0,1); b.appendEntryTopLeft(1,2); b.appendEntryTopRight(0,3); b.appendEntryTopRight(1,4); b.appendEntryTopRight(2,5); b.rowDoneTopLeftAndRight(); b.appendEntryBottomLeft(0,6); b.appendEntryBottomLeft(1,7); b.appendEntryBottomRight(0,8); b.appendEntryBottomRight(1,9); b.appendEntryBottomRight(2,10); b.rowDoneBottomLeftAndRight(); auto matrix = b.buildMatrixAndClear(); matrix.leftColumnMonomials = monoLeft; matrix.rightColumnMonomials = monoRight; const char* matrixStr1 = "Left columns: 1 a\n" "Right columns: b bcd bc\n" "0: 0#1 1#2 | 0: 0#3 1#4 2#5 \n" " | \n" "0: 0#6 1#7 | 0: 0#8 1#9 2#10\n"; ASSERT_EQ(matrixStr1, matrix.toString()); const char* matrixStr2 = "Left columns: a 1\n" "Right columns: bcd bc b\n" "0: 1#1 0#2 | 0: 2#3 0#4 1#5 \n" " | \n" "0: 1#6 0#7 | 0: 2#8 0#9 1#10\n"; matrix.sortColumnsLeftRightParallel(); ASSERT_EQ(matrixStr2, matrix.toString()); matrix.sortColumnsLeftRightParallel(); ASSERT_EQ(matrixStr2, matrix.toString()); } } TEST(QuadMatrixBuilder, BuildAndClear) { std::unique_ptr ring(ringFromString("32003 6 1\n1 1 1 1 1 1")); QuadMatrixBuilder::Map map(*ring); QuadMatrixBuilder::Monomials monoLeft; QuadMatrixBuilder::Monomials monoRight; QuadMatrixBuilder b(*ring, map, monoLeft, monoRight); createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b); b.appendEntryTopLeft(1, 1); b.appendEntryTopRight(2, 2); b.rowDoneTopLeftAndRight(); b.appendEntryBottomLeft(1, 3); b.appendEntryBottomRight(2, 4); b.rowDoneBottomLeftAndRight(); QuadMatrix qm(b.buildMatrixAndClear()); qm.leftColumnMonomials = monoLeft; qm.rightColumnMonomials = monoRight; // test that the quad matrix is right ASSERT_EQ("0: 1#1\n", qm.topLeft.toString()); ASSERT_EQ("0: 2#2\n", qm.topRight.toString()); ASSERT_EQ("0: 1#3\n", qm.bottomLeft.toString()); ASSERT_EQ("0: 2#4\n", qm.bottomRight.toString()); ASSERT_EQ(2, qm.leftColumnMonomials.size()); ASSERT_EQ(3, qm.rightColumnMonomials.size()); const auto& monoid = ring->monoid(); ASSERT_EQ("a", monoToStr(monoid, *qm.leftColumnMonomials[0])); ASSERT_EQ("b", monoToStr(monoid, *qm.rightColumnMonomials[0])); } mathicgb-master/src/test/Range.cpp000077500000000000000000000144101311555162500174420ustar00rootroot00000000000000#include #include #include // MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/Range.hpp" #include #include #include #include #include using namespace mgb; namespace { template void checkRange(const Range1& r1, const Range2& r2) { const auto d1 = std::distance(std::begin(r1), std::end(r1)); const auto d2 = std::distance(std::begin(r2), std::end(r2)); ASSERT_EQ(d1, d2); ASSERT_TRUE(std::equal(std::begin(r1), std::end(r1), std::begin(r2))); } } TEST(Range, Simple) { int intArray[] = {1, 5, 3, 7}; const std::vector intVector(std::begin(intArray), std::end(intArray)); const std::list intList(std::begin(intArray), std::end(intArray)); std::vector v; auto checkClear = [&]() { checkRange(intVector, v); v.clear(); }; // Let's try the pattern without using range just to make sure everything // is OK. for (const auto& i : intArray) v.push_back(i); checkClear(); // *** check using intArray. for (const auto& i : range(intArray)) v.push_back(i); checkClear(); for (const auto& i : range(std::begin(intArray), std::end(intArray))) v.push_back(i); checkClear(); // *** check using intVector for (const auto& i : range(intVector)) v.push_back(i); checkClear(); for (const auto& i : range(std::begin(intVector), std::end(intVector))) v.push_back(i); checkClear(); // *** check using intList for (const auto& i : range(intList)) v.push_back(i); checkClear(); for (const auto& i : range(std::begin(intList), std::end(intList))) v.push_back(i); checkClear(); // *** check using iterated range for (const auto& i : range(range(std::begin(intArray), std::end(intArray)))) v.push_back(i); checkClear(); for (const auto& i : range(range(intVector))) v.push_back(i); checkClear(); for (const auto& i : range(range(range(range(intList))))) v.push_back(i); checkClear(); } TEST(Range, rangeToVector) { int intArray[] = {1, 5, 3, 7}; const std::vector intVector(std::begin(intArray), std::end(intArray)); ASSERT_EQ(intVector, rangeToVector(std::begin(intArray), std::end(intArray))); ASSERT_EQ(intVector, rangeToVector(intArray)); ASSERT_EQ(intVector, rangeToVector(range(intArray))); } TEST(Range, zip) { const std::string a[] = {"hello", "world"}; const int b[] = {4, 2, 1, 0}; std::ostringstream out; // Put a range() around b just to test something other than a built-in for (const auto& p : zip(a, range(b))) out << p.first << p.second << ' '; ASSERT_EQ("hello4 world2 ", out.str()); // Now try the version on iterators and put the range around a instead. out.str(""); for ( const auto& p : zip(std::begin(range(a)), std::end(range(a)), std::begin(b), std::end(b)) ) out << p.first << p.second << ' '; ASSERT_EQ("hello4 world2 ", out.str()); } TEST(Range, intRange) { const int int05[] = {0, 1, 2, 3, 4}; ASSERT_EQ(rangeToVector(int05), rangeToVector(intRange(0, 5))); ASSERT_EQ(rangeToVector(int05), rangeToVector(intRange(5))); // gcc 4.7.3 won't parse "const signed char" here, but it will parse // it like this with the typedef. typedef signed char C; const C scharm2p5[] = {-2, -1, 0, 1, 2, 3, 4}; ASSERT_EQ( rangeToVector(range(scharm2p5)), rangeToVector(intRange(C(-2), C(5))) ); // Normally we should not dereference an end() iterator, but for the case // of intRange() it is OK. ASSERT_EQ(std::numeric_limits::max(), *intRange().end()); ASSERT_EQ(size_t(0), *intRange().begin()); } TEST(Range, indexRange) { typedef std::pair Pair; Pair indexed[] = {Pair(-2, 0), Pair(-1, 1), Pair(0, 2)}; ASSERT_EQ( rangeToVector(indexed), rangeToVector(indexRange(intRange(-2, 1))) ); } TEST(Range, oppositePairRange) { /// MES: The following commented out code using arrays of strings, and /// iterators/ranges of them, fails to compile on clang, 1 Jan 2017 /// (clang version 3.8, and also on earlier versions of clang): // If one uses // std::string elems[] {"hello", "world", "!"}; // instead of int elems[] {1,13,17}; // this doesn't compile. Why not?? const auto r = zip(elems, intRange(10)); const auto opR = zip(intRange(3), elems); auto val1 = rangeToVector(r); auto val2a = oppositePairRange(opR); auto val3a = std::begin(val2a); auto val3b = std::end(val2a); auto val3 = rangeToVector(val3a,val3b); auto val2 = rangeToVector(val2a); ASSERT_EQ(val1, val2); ASSERT_EQ(rangeToVector(r), rangeToVector(oppositePairRange(opR))); ASSERT_EQ( rangeToVector(opR), rangeToVector(oppositePairRange(std::begin(r), std::end(r))) ); } TEST(Range, adjPairRange) { typedef std::pair Pair; std::vector none; ASSERT_EQ(rangeToVector(none), rangeToVector(adjPairRange(intRange(0)))); ASSERT_EQ(rangeToVector(none), rangeToVector(adjPairRange(intRange(1)))); Pair adj2[] = {Pair(0, 1)}; ASSERT_EQ(rangeToVector(adj2), rangeToVector(adjPairRange(intRange(2)))); Pair adj4[] = {Pair(0, 1), Pair(1, 2), Pair(2, 3)}; ASSERT_EQ(rangeToVector(adj4), rangeToVector(adjPairRange(intRange(4)))); } TEST(Range, flatten) { std::vector> v(3); v[0].push_back(1); v[2].push_back(2); v[2].push_back(3); std::ostringstream out; for (const auto& i : flatten(v)) out << i << ' '; ASSERT_EQ("1 2 3 ", out.str()); } TEST(Range, flattenRecursive) { std::list>> outer; outer.emplace_back(); outer.emplace_back(); outer.back().emplace_back(); outer.back().emplace_back(); outer.back().back().insert(1); outer.back().emplace_back(); outer.back().back().insert(2); outer.back().emplace_back(); outer.back().emplace_back(); outer.back().back().insert(3); outer.back().back().insert(4); outer.back().back().insert(5); outer.back().back().insert(6); outer.back().emplace_back(); outer.back().back().insert(7); outer.back().emplace_back(); outer.back().emplace_back(); std::ostringstream out; for (const auto& i : flatten(flatten(outer))) out << i << ' '; ASSERT_EQ("1 2 3 4 5 6 7 ", out.str()); } mathicgb-master/src/test/Scanner.cpp000077500000000000000000000064671311555162500200140ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/Scanner.hpp" #include using namespace mgb; namespace { const char* const alpha = "abcdefghijkl"; const char* const alphaSpaced = "a bc def ghij kl"; const char* const alphas[] = {"a", "bc", "def", "ghij", "kl"}; } TEST(Scanner, NoOp) { std::istringstream in; Scanner sc(in); } TEST(Scanner, PeekAndGet) { std::stringstream s(alphaSpaced); Scanner in(s); for (size_t i = 0; alpha[i] != '\0'; ++i) { ASSERT_EQ(alphaSpaced[i], in.peek()); ASSERT_EQ(alphaSpaced[i], in.get()); } } TEST(Scanner, Match) { std::stringstream s(alphaSpaced); Scanner in(s); for (size_t i = 0; alpha[i] != '\0'; ++i) { ASSERT_FALSE(in.match('!')); ASSERT_FALSE(in.matchEOF()); ASSERT_TRUE(in.match(alpha[i])); } ASSERT_TRUE(in.matchEOF()); } TEST(Scanner, ExpectChar) { std::stringstream s(alphaSpaced); Scanner in(s); for (size_t i = 0; alpha[i] != '\0'; ++i) in.expect(alpha[i]); in.expectEOF(); } TEST(Scanner, ExpectTwoChars) { Scanner in(alphaSpaced); for (size_t i = 0; alpha[i] != '\0'; ++i) { if (i % 2 == 0) in.expect('!', alpha[i]); else in.expect(alpha[i], '!'); } in.expectEOF(); } TEST(Scanner, ExpectString) { Scanner in(alphaSpaced); const auto size = sizeof(alphas) / sizeof(*alphas); for (size_t i = 0; i < size; ++i) { if (i % 2 == 0) in.expect(alphas[i]); else in.expect(std::string(alphas[i])); } } TEST(Scanner, MatchString) { Scanner in(alphaSpaced); const auto size = sizeof(alphas) / sizeof(*alphas); for (size_t i = 0; i < size; ++i) { ASSERT_FALSE(in.match("ef")); ASSERT_FALSE(in.match("deq")); ASSERT_TRUE(in.match(alphas[i])); } } TEST(Scanner, readModular) { PrimeField f(11); std::stringstream s("0 1 1 +0 -0 +1 -1 15 255 -255"); Scanner in(s); ASSERT_EQ(f.zero(), in.readModular(f)); ASSERT_EQ(f.one(), in.readModular(f)); ASSERT_EQ(f.minusOne(), in.readModular(f, true)); ASSERT_EQ(f.zero(), in.readModular(f)); ASSERT_EQ(f.zero(), in.readModular(f)); ASSERT_EQ(f.one(), in.readModular(f)); ASSERT_EQ(f.minusOne(), in.readModular(f)); ASSERT_EQ(f.toElement(4), in.readModular(f)); ASSERT_EQ(f.toElement(2), in.readModular(f)); ASSERT_EQ(f.toElement(9), in.readModular(f)); } TEST(Scanner, readInteger) { std::stringstream s("0 1 +0 -0 +1 -1 127 -128 128"); Scanner in(s); ASSERT_EQ(0, in.readInteger()); ASSERT_EQ(1, in.readInteger()); ASSERT_EQ(0, in.readInteger()); ASSERT_EQ(0, in.readInteger()); ASSERT_EQ(1, in.readInteger()); ASSERT_EQ(-1, in.readInteger()); ASSERT_EQ(127, in.readInteger()); ASSERT_EQ(-128, in.readInteger()); ASSERT_EQ(-128, in.readInteger(true)); } TEST(Scanner, WhiteAndLineCount) { std::stringstream s(" \t\n\rx\n\n\ny"); Scanner in(s); ASSERT_EQ(1, in.lineCount()); ASSERT_TRUE(in.peek() == ' '); ASSERT_TRUE(in.peekWhite()); in.eatWhite(); ASSERT_TRUE(in.peek() == 'x'); ASSERT_TRUE(in.match('x')); ASSERT_EQ(2, in.lineCount()); ASSERT_TRUE(in.match('y')); in.expectEOF(); ASSERT_EQ(5, in.lineCount()); } mathicgb-master/src/test/SparseMatrix.cpp000077500000000000000000000052601311555162500210330ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/SparseMatrix.hpp" #include "mathicgb/Poly.hpp" #include "mathicgb/PolyRing.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/MathicIO.hpp" #include #include #include using namespace mgb; namespace { std::unique_ptr parsePoly(const PolyRing& ring, std::string str) { std::istringstream in(str); Scanner scanner(in); return make_unique(MathicIO<>().readPoly(ring, false, scanner)); } } TEST(SparseMatrix, NoRows) { SparseMatrix mat; // test a matrix with no rows ASSERT_EQ(0, mat.entryCount()); ASSERT_EQ(0, mat.rowCount()); ASSERT_EQ(0, mat.computeColCount()); ASSERT_EQ("matrix with no rows\n", mat.toString()); } TEST(SparseMatrix, Simple) { SparseMatrix mat; mat.appendEntry(5, 101); mat.rowDone(); ASSERT_EQ(1, mat.entryCount()); ASSERT_EQ(1, mat.rowCount()); ASSERT_EQ(6, mat.computeColCount()); ASSERT_EQ(5, mat.leadCol(0)); ASSERT_EQ(1, mat.entryCountInRow(0)); ASSERT_EQ("0: 5#101\n", mat.toString()); ASSERT_FALSE(mat.emptyRow(0)); mat.rowDone(); // add a row with no entries ASSERT_EQ(1, mat.entryCount()); ASSERT_EQ(2, mat.rowCount()); ASSERT_EQ(6, mat.computeColCount()); ASSERT_EQ(5, mat.leadCol(0)); ASSERT_EQ(0, mat.entryCountInRow(1)); ASSERT_EQ("0: 5#101\n1:\n", mat.toString()); ASSERT_TRUE(mat.emptyRow(1)); mat.appendEntry(5, 102); mat.appendEntry(2001, 0); // scalar zero mat.rowDone(); // add a row with two entries ASSERT_EQ(3, mat.entryCount()); ASSERT_EQ(3, mat.rowCount()); ASSERT_EQ(2002, mat.computeColCount()); ASSERT_EQ(5, mat.leadCol(2)); ASSERT_EQ(2, mat.entryCountInRow(2)); ASSERT_EQ("0: 5#101\n1:\n2: 5#102 2001#0\n", mat.toString()); ASSERT_FALSE(mat.emptyRow(2)); } TEST(SparseMatrix, toRow) { auto ring = ringFromString("32003 6 1\n1 1 1 1 1 1"); auto polyForMonomials = parsePoly(*ring, "a5+a4+a3+a2+a1+a0"); std::vector monomials; for (auto it = polyForMonomials->begin(); it != polyForMonomials->end(); ++it) monomials.push_back(it.mono().ptr()); SparseMatrix mat(5); mat.clear(); mat.rowDone(); mat.appendEntry(0,10); mat.rowDone(); mat.appendEntry(2,20); mat.appendEntry(3,0); mat.appendEntry(4,40); mat.rowDone(); Poly p(*ring); mat.rowToPolynomial(0, monomials, p); ASSERT_EQ(*parsePoly(*ring, "0"), p); mat.rowToPolynomial(1, monomials, p); ASSERT_EQ(*parsePoly(*ring, "10a5"), p); mat.rowToPolynomial(2, monomials, p); ASSERT_EQ(*parsePoly(*ring, "20a3+40a1"), p); } mathicgb-master/src/test/gb-test.cpp000077500000000000000000000301441311555162500177550ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/Poly.hpp" #include "mathicgb/Basis.hpp" #include "mathicgb/ModuleMonoSet.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/SigPolyBasis.hpp" #include "mathicgb/SignatureGB.hpp" #include "mathicgb/ClassicGBAlg.hpp" #include "mathicgb/mtbb.hpp" #include "mathicgb/MathicIO.hpp" #include "mathicgb/Scanner.hpp" #include "test/ideals.hpp" #include #include #include #include #include #include using namespace mgb; TEST(IO, ideal) { const char* idealA_fromStr_format = "32003 6 \ 1 1 1 1 1 1 1 \ 3 \ -bc+ad \ -b2+af \ -bc2+a2e \ "; std::unique_ptr I = basisParseFromString(idealA_fromStr_format); EXPECT_EQ(" -bc+ad\n -b2+af\n -bc2+a2e\n", toString(I.get())); } void testGB( std::string idealStr, std::string sigBasisStr, std::string syzygiesStr, std::string initialIdealStr, size_t nonSingularReductions ) { // Put the contents of pict.out into allPairsTest as a string. This // works because pict.out does not have any commas and we do not // care about whitespace. pict.out contains a set of tests such that // all pairs of parameters are covered by at least one test. See // pict.in for details. #define MATHICGB_ESCAPE_MULTILINE_STRING(str) #str char const allPairsTests[] = MATHICGB_ESCAPE_MULTILINE_STRING( spairQueue reducerType divLookup monTable buchberger postponeKoszul useBaseDivisors autoTailReduce autoTopReduce preferSparseReducers useSingularCriterionEarly sPairGroupSize threadCount 0 25 4 1 1 0 0 0 0 0 0 1 1 3 11 3 2 0 1 1 0 0 1 1 100 2 1 9 1 4 1 0 0 1 1 1 0 2 8 2 21 2 3 1 0 0 1 1 0 0 10 2 1 9 2 4 0 1 1 0 0 0 1 1 2 2 7 1 3 0 0 1 0 0 1 1 1 8 0 21 4 1 0 1 0 0 0 1 1 100 1 3 26 3 2 1 0 0 0 1 1 0 10 1 3 26 3 1 1 0 0 1 1 0 0 1 8 0 25 4 2 1 0 0 1 1 1 0 0 8 0 14 1 1 0 1 1 0 0 0 1 10 8 2 22 4 4 1 0 0 1 0 0 0 10 1 1 14 4 3 0 1 1 0 0 1 0 2 1 2 10 2 2 0 1 1 0 0 0 1 2 2 3 17 2 1 0 1 1 0 0 0 1 0 2 0 18 1 2 0 1 1 0 0 1 1 1 2 0 23 2 3 1 0 0 1 1 1 0 10 1 1 10 3 4 1 0 0 1 1 0 0 100 8 2 19 3 3 0 1 1 0 0 0 1 0 1 0 26 4 1 1 0 0 0 0 1 0 2 2 3 13 1 4 1 0 0 1 0 1 0 2 1 1 15 2 1 1 0 0 1 0 0 0 10 8 0 21 3 4 1 0 0 1 1 0 0 2 8 3 10 4 3 0 0 1 0 0 1 1 1 1 1 12 1 2 0 0 1 0 0 0 1 10 8 2 19 1 1 1 0 0 1 1 1 0 100 8 1 19 4 2 1 0 0 0 1 1 0 10 2 1 16 1 4 1 0 0 0 1 1 0 0 1 1 26 2 3 1 0 0 1 0 0 0 100 8 2 16 4 3 0 1 1 0 0 0 1 1 2 0 7 2 1 1 0 0 1 1 0 0 10 2 3 9 4 2 0 1 0 0 0 0 1 10 1 1 17 3 3 1 0 0 1 1 1 0 10 1 1 23 1 2 0 1 1 0 0 0 1 1 2 2 14 3 4 1 0 0 1 1 1 0 100 2 1 7 4 4 1 0 0 1 1 0 0 2 1 1 13 4 3 0 1 1 0 0 0 1 1 2 3 23 4 1 0 0 1 0 0 0 1 0 8 3 7 3 2 0 1 1 0 0 1 1 0 2 0 17 1 2 1 0 0 1 1 0 0 100 8 0 10 1 1 0 1 1 0 0 1 0 10 8 0 12 2 4 1 0 0 1 1 1 0 1 2 2 12 4 1 1 0 0 1 1 1 0 0 1 1 18 4 1 1 0 0 1 1 0 0 2 8 1 22 1 1 0 1 1 0 0 1 1 2 2 1 21 1 2 0 0 1 0 0 0 1 0 1 2 11 4 4 1 0 0 1 1 0 0 10 8 0 15 3 3 0 1 1 0 0 1 1 1 2 2 23 3 4 1 0 0 0 0 0 0 2 8 2 17 4 4 0 1 0 0 0 0 1 2 1 0 13 2 2 1 0 0 1 1 1 0 0 8 2 13 3 1 0 1 1 0 0 0 1 100 2 0 9 3 1 1 0 0 1 0 1 0 0 8 0 20 1 3 0 1 0 0 0 1 1 2 8 0 11 1 3 1 0 0 0 1 1 0 1 1 2 8 1 4 1 0 0 1 0 1 0 2 1 1 20 2 1 1 0 0 1 1 0 0 100 2 0 22 2 3 0 0 0 0 0 0 1 100 8 1 13 4 4 1 0 0 0 0 1 0 10 8 0 16 3 2 0 1 0 0 0 1 1 2 8 3 22 3 2 0 0 0 0 0 1 1 0 8 1 8 2 1 0 1 1 0 0 0 1 10 8 0 19 2 4 0 1 1 0 0 0 1 1 8 1 11 2 1 1 0 0 1 0 0 0 0 2 3 15 1 2 1 0 0 0 1 0 0 100 1 1 17 4 3 0 1 0 0 0 1 1 1 1 3 24 2 4 0 1 1 0 0 1 1 1 8 2 24 3 3 1 0 0 1 1 0 0 2 1 3 8 3 2 1 0 0 1 1 0 0 100 2 3 21 3 4 0 0 0 0 0 0 0 1 8 2 26 1 4 1 0 0 1 1 0 0 0 2 3 14 2 2 0 1 1 0 0 1 1 0 1 0 8 4 3 0 0 1 0 0 0 1 1 1 2 9 1 3 1 0 0 1 0 1 0 100 2 3 12 3 3 0 1 1 0 0 0 1 100 8 0 7 1 4 1 0 0 1 1 1 0 100 8 0 10 4 2 0 0 1 0 0 0 1 0 2 1 24 4 1 0 0 1 0 0 0 1 0 2 3 16 2 1 0 0 0 0 0 1 1 10 1 3 18 2 3 0 1 1 0 0 1 1 0 1 2 16 3 4 0 1 1 0 0 0 1 100 8 0 11 1 3 0 0 1 0 0 0 1 2 1 2 14 2 2 0 1 0 0 0 0 1 1 8 2 12 4 3 1 0 0 1 1 1 0 2 8 0 8 1 4 0 0 1 0 0 0 1 0 1 3 25 2 3 1 0 0 1 0 1 0 2 2 2 15 4 4 1 0 0 1 1 0 0 2 1 3 20 3 2 1 0 0 1 1 0 0 0 1 3 23 4 4 0 1 1 0 0 0 1 100 2 2 25 3 4 1 0 0 0 0 1 0 100 2 1 25 1 2 1 0 0 0 1 1 0 10 8 0 24 1 2 0 0 1 0 0 1 1 10 1 1 15 4 3 1 0 0 1 1 1 0 0 2 1 24 3 4 0 1 0 0 0 0 1 100 1 2 20 4 4 0 1 1 0 0 1 0 1 1 1 22 4 3 1 0 0 0 1 0 0 1 2 2 18 3 4 0 0 0 0 0 0 0 100 8 3 19 2 4 0 0 0 0 0 0 1 2 1 2 18 1 1 1 0 0 0 1 0 0 10 1 3 16 2 3 1 0 0 1 1 1 0 10 8 2 20 4 1 0 1 1 0 0 0 1 10 8 ); std::istringstream tests(allPairsTests); // skip the initial line with the parameter names. { char const* params[] = { "spairQueue", "reducerType", "divLookup", "monTable", "buchberger", "postponeKoszul", "useBaseDivisors", "autoTailReduce", "autoTopReduce", "preferSparseReducers", "useSingularCriterionEarly", "sPairGroupSize", "threadCount"}; std::string paramName; size_t const paramCount = sizeof(params) / sizeof(*params); for (size_t i = 0; i < paramCount; ++i) { tests >> paramName; // This assert will fire if you changed the order of the // parameters, renamed a parameter, removed a parameter or added // a parameter. Unless all you did was to rename a parameter, // don't just update the params array that the assert is based // on - you also need to update the code below that parses the // pict output because it depends on the order of the // parameters. MATHICGB_ASSERT(paramName == params[i]); } } while (true) { // parse a line of the pict file int spairQueue; tests >> spairQueue; if (!tests) break; // no more tests MATHICGB_ASSERT(0 <= spairQueue && spairQueue <= 3); int reducerType; tests >> reducerType; MATHICGB_ASSERT(0 <= reducerType && reducerType <= 30); int divLookup; tests >> divLookup; MATHICGB_ASSERT(1 <= divLookup && divLookup <= 4); int monTable; tests >> monTable; MATHICGB_ASSERT(1 <= monTable && monTable <= 4); int buchberger; tests >> buchberger; MATHICGB_ASSERT(0 <= buchberger && buchberger <= 1); int postponeKoszul; tests >> postponeKoszul; MATHICGB_ASSERT(0 <= postponeKoszul && postponeKoszul <= 1); int useBaseDivisors; tests >> useBaseDivisors; MATHICGB_ASSERT(0 <= useBaseDivisors && useBaseDivisors <= 1); int autoTailReduce; tests >> autoTailReduce; MATHICGB_ASSERT(0 <= autoTailReduce && autoTailReduce <= 1); int autoTopReduce; tests >> autoTopReduce; MATHICGB_ASSERT(0 <= autoTopReduce && autoTopReduce <= 1); int preferSparseReducers; tests >> preferSparseReducers; MATHICGB_ASSERT(0 <= preferSparseReducers && preferSparseReducers <= 1); int useSingularCriterionEarly; tests >> useSingularCriterionEarly; MATHICGB_ASSERT(0 <= useSingularCriterionEarly); MATHICGB_ASSERT(useSingularCriterionEarly <= 1); int sPairGroupSize; tests >> sPairGroupSize; MATHICGB_ASSERT(0 <= sPairGroupSize); int threadCount; tests >> threadCount; MATHICGB_ASSERT(0 <= threadCount); // Rule out combinations of parameter values that do not make sense. // These are asserts because pict should have already removed these // combinations. MATHICGB_ASSERT(buchberger || !autoTopReduce); MATHICGB_ASSERT(buchberger || !autoTailReduce); MATHICGB_ASSERT(buchberger || reducerType != 25); MATHICGB_ASSERT(buchberger || reducerType != 26); MATHICGB_ASSERT(!buchberger || !postponeKoszul); MATHICGB_ASSERT(!buchberger || !useBaseDivisors); MATHICGB_ASSERT(!buchberger || !useSingularCriterionEarly); // check that we have a valid reducer type Reducer::ReducerType red = Reducer::ReducerType(reducerType); MATHICGB_ASSERT(static_cast(red) == reducerType); std::istringstream inStream(idealStr); Scanner in(inStream); auto p = MathicIO<>().readRing(true, in); auto& ring = *p.first; auto& processor = p.second; auto basis = MathicIO<>().readBasis(ring, false, in); if (processor.schreyering()) processor.setSchreyerMultipliers(basis); MATHICGB_ASSERT(Reducer::makeReducerNullOnUnknown(red, ring).get() != 0); mgb::mtbb::task_scheduler_init scheduler(threadCount); if (buchberger) { const auto reducer = Reducer::makeReducer (Reducer::reducerType(reducerType), ring); ClassicGBAlgParams params; params.reducer = reducer.get(); params.monoLookupType = divLookup; params.preferSparseReducers = preferSparseReducers; params.sPairQueueType = spairQueue; params.breakAfter = 0; params.printInterval = 0; params.sPairGroupSize = sPairGroupSize; params.reducerMemoryQuantum = 100 * 1024; params.useAutoTopReduction = autoTopReduce; params.useAutoTailReduction = autoTailReduce; params.callback = nullptr; auto gb = computeGBClassicAlg(std::move(basis), params); Basis initialIdeal(gb.ring()); for (size_t i = 0; i < gb.size(); ++i) { auto poly = make_unique(gb.ring()); auto leadTerm = gb.getPoly(i)->leadTerm(); leadTerm.coef = gb.ring().field().one(); poly->append(leadTerm); initialIdeal.insert(std::move(poly)); } initialIdeal.sort(); EXPECT_EQ(initialIdealStr, toString(&initialIdeal)) << reducerType << ' ' << divLookup << ' ' << monTable << ' ' << postponeKoszul << ' ' << useBaseDivisors; } else { SignatureGB alg( std::move(basis), std::move(processor), Reducer::reducerType(reducerType), divLookup, monTable, postponeKoszul, useBaseDivisors, preferSparseReducers, useSingularCriterionEarly, spairQueue ); alg.computeGrobnerBasis(); EXPECT_EQ(sigBasisStr, toString(alg.getGB(), 1)) << reducerType << ' ' << divLookup << ' ' << monTable << ' ' << ' ' << postponeKoszul << ' ' << useBaseDivisors; EXPECT_EQ(syzygiesStr, toString(alg.getSyzTable())) << reducerType << ' ' << divLookup << ' ' << monTable << ' ' << ' ' << postponeKoszul << ' ' << useBaseDivisors; /*EXPECT_EQ(nonSingularReductions, alg.getSigReductionCount() - alg.getSingularReductionCount()) << reducerType << ' ' << divLookup << ' ' << monTable << ' ' << ' ' << postponeKoszul << ' ' << useBaseDivisors;*/ } } } TEST(GB, small) { testGB(smallIdealComponentLastDescending(), idealSmallBasis, idealSmallSyzygies, idealSmallInitial, 7); } TEST(GB, liu_0_1) { testGB(liuIdealComponentLastDescending(), liu_gb_strat0_free1, liu_syzygies_strat0_free1, liu_initial_strat0_free1, 13); } TEST(GB, weispfennig97_0_4) { testGB(weispfennig97IdealComponentLast(true), weispfennig97_gb_strat0_free4, weispfennig97_syzygies_strat0_free4, weispfennig97_initial_strat0_free4, 31); } TEST(GB, weispfennig97_0_5) { testGB(weispfennig97IdealComponentLast(false), weispfennig97_gb_strat0_free5, weispfennig97_syzygies_strat0_free5, weispfennig97_initial_strat0_free5, 27); } TEST(GB, gerdt93_0_1) { testGB(gerdt93IdealComponentLast(false, false), gerdt93_gb_strat0_free1, gerdt93_syzygies_strat0_free1, gerdt93_initial_strat0_free1, 9); } TEST(GB, gerdt93_0_2) { testGB(gerdt93IdealComponentMiddle(true), gerdt93_gb_strat0_free2, gerdt93_syzygies_strat0_free2, gerdt93_initial_strat0_free2, 7); } TEST(GB, gerdt93_0_3) { testGB(gerdt93IdealComponentMiddle(false), gerdt93_gb_strat0_free3, gerdt93_syzygies_strat0_free3, gerdt93_initial_strat0_free3, 9); } TEST(GB, gerdt93_0_4) { testGB(gerdt93IdealComponentLast(true, true), gerdt93_gb_strat0_free4, gerdt93_syzygies_strat0_free4, gerdt93_initial_strat0_free4, 7); } TEST(GB, gerdt93_0_5) { testGB(gerdt93IdealComponentLast(false, true), gerdt93_gb_strat0_free5, gerdt93_syzygies_strat0_free5, gerdt93_initial_strat0_free5, 7); } TEST(GB, gerdt93_0_6) { testGB(gerdt93IdealComponentFirst(true), gerdt93_gb_strat0_free6, gerdt93_syzygies_strat0_free6, gerdt93_initial_strat0_free6, 7); } TEST(GB, gerdt93_0_7) { testGB(gerdt93IdealComponentFirst(false), gerdt93_gb_strat0_free7, gerdt93_syzygies_strat0_free7, gerdt93_initial_strat0_free7, 9); } mathicgb-master/src/test/gtestInclude.cpp000077500000000000000000000012071311555162500210400ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" // Includes a file from gtest that pulls in all of the implementation // of gtest. The gtest docs recommend building gtest individually for // each program rather than using an installed gtest and this is as // easy a way of doing it as any. Especially because it guarantees that // the compiler flags are the same, which is the whole point of the // recommendation to build gtest for each program. namespace mgb {} using namespace mgb; #include "src/gtest-all.cc" mathicgb-master/src/test/ideals.cpp000077500000000000000000000641661311555162500176640ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "test/ideals.hpp" #include using namespace mgb; std::string smallIdealComponentLastDescending() { return "32003 6\n" "1 1 1 1 1 1 1\n" "_revlex revcomponent\n" "3\n" "-bc+ad\n" "-b2+af\n" "-bc2+a2e\n"; } const char* idealSmallBasis = "\ 0 <0> bc-ad\n\ 1 <1> b2-af\n\ 2 <2> bc2-a2e\n\ 3 c<0> acd-a2e\n\ 4 b<0> abd-acf\n\ 5 c2<1> a2be-ac2f\n\ 6 bc<0> a2d2-ac2f\n\ 7 c3<1> a3de-ac3f\n\ 8 c4<1> a4e2-ac4f\n\ "; const char* idealSmallSyzygies = " 0: b2 bc2 \n 1: c2d bc2 \n"; const char* idealSmallInitial = " bc\n b2\n acd\n abd\n a2be\n a2d2\n a3de\n a4e2\n"; std::string liuIdealComponentLastDescending() { return "2 6\n" "1 1 1 1 1 1 1\n" "_revlex revcomponent\n" "4\n" "bc+bd+af+ef\n" "ac+cd+bf+ef\n" "ad+bd+cf+ef\n" "ab+ac+df+ef\n"; } const char* liu_gb_strat0_free1 = "\ 0 <0> bc+bd+af+ef\n\ 1 <1> ac+cd+bf+ef\n\ 2 <2> ad+bd+cf+ef\n\ 3 <3> ab+ac+df+ef\n\ 4 c<2> bd2+cd2+c2f+cef+cf2+ef2\n\ 5 b<2> b2d+cd2+d2f+bef+af2+ef2\n\ 6 b<1> c2d+cd2+b2f+c2f+cdf+bef+cef+def+af2+ef2\n\ 7 a<0> a2f+b2f+c2f+d2f+aef+bef+cef+def\n\ 8 ad<0> cd2f+d3f+cdef+d2ef+b2f2+c2f2+bdf2+aef2+def2+e2f2+bf3+ef3\n\ 9 c2<2> c3f+d3f+c2ef+bdef+cdef+d2ef+b2f2+c2f2+d2f2+aef2+bef2+e2f2+af3+bf3\n\ 10 b2<1> b3f+d3f+b2ef+d2ef+b2f2+c2f2+bef2+cef2+bf3+df3\n\ 11 c2d<2> b2ef2+d2ef2+be2f2+de2f2+b2f3+d2f3+aef3+cef3+af4+bf4+cf4+df4\n\ 12 c2d2<2> bde2f2+cde2f2+c2ef3+d2ef3+ae2f3+e3f3+c2f4+bdf4+cdf4+d2f4+aef4+def4+df5+ef5\n\ 13 c2d3<2> c2e2f3+d2e2f3+ce3f3+de3f3+c2ef4+d2ef4+be2f4+ce2f4+aef5+cef5+af6+bf6+cf6+df6\n\ 14 c2d4<2> cde2f4+d2e2f4+ae3f4+be3f4+ce3f4+e4f4+ce2f5+e3f5+cdf6+d2f6+aef6+bef6+cef6+e2f6+cf7+ef7\n\ 15 c2d5<2> d2e3f4+de4f4+ae3f5+be3f5+d2ef6+be2f6+aef7+bef7+bf8+df8\n\ "; const char* liu_syzygies_strat0_free1 = " 0: ac ab a2d \n 1: ab b2d b2c \n 2: bc ac ab c3d \n"; const char* liu_initial_strat0_free1 = " ad\n bc\n ac\n ab\n a2f\n bd2\n c2d\n b2d\n cd2f\n c3f\n b3f\n b2ef2\n bde2f2\n c2e2f3\n cde2f4\n d2e3f4\n"; std::string weispfennig97IdealComponentLast(bool componentsAscending) { std::ostringstream out; out << "7583 4 schreyer revlex 1\n"; if (componentsAscending) out << "1 1 1 1 _revlex component\n"; else out << "1 1 1 1 _revlex revcomponent\n"; out << "3\n" "b4+ab2c+a2d2-2abd2+b2d2+c2d2 \n" "a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5 \n" "a3b2-abc3+a2d3+b2d3+c2d3\n"; return out.str(); } const char* weispfennig97_gb_strat0_free4 = "\ 0 <0> b4+ab2c+a2d2-2abd2+b2d2+c2d2\n\ 1 <1> a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5\n\ 2 <2> a3b2-abc3+a2d3+b2d3+c2d3\n\ 3 c<2> a4d2+a2b2d2+a2c2d2-a2cd3-b2cd3-c3d3+3ad5\n\ 4 b2<1> b3c4+abc5-2a3bcd2-ab2c2d2-abc3d2+bc4d2-2a2bd4+a2d5-2b2d5-3acd5+c2d5-3d7\n\ 5 b2<2> ab3c3+a2bc4+2a2b3d2+2a2bc2d2-a2b2d3-2a2bcd3+ab2cd3-2b3cd3-b2c2d3-2bc3d3-2a2d5+4abd5+b2d5+c2d5\n\ 6 b3<1> ab3c2d2+ab2c3d2+a2c4d2+c6d2+2a2b2d4-a2bd5+2b3d5-2a2cd5+3abcd5-2b2cd5-bc2d5-2c3d5+3bd7\n\ 7 b2c<2> a2bc3d2-abc4d2+bc5d2+ab2c2d3-b2c3d3-bc4d3+2a3bd4-a3cd4-ab2cd4-ac3d4+3ab2d5+a2cd5-2abcd5+b2cd5+c3d5+3ad7-3cd7+3d8\n\ 8 b3<2> a3c3d2+ab2c3d2+ac5d2+a2b3d3-ab3cd3+b3c2d3-2a3d5+2a2bd5-b3d5-2ac2d5-bc2d5\n\ 9 ab2<2> a3bc4+b2c6+a3bc2d2+3ab2c3d2+a2c4d2-abc4d2+c6d2-2a3bcd3-2ab3cd3-ab2c2d3-3abc3d3+bc4d3+2a2b2d4-3a3d5+a2bd5-2a2cd5+3abcd5-2b2cd5-6bc2d5-2c3d5+a2d6+b2d6+c2d6+3bd7-3d8\n\ 10 b3c<1> a2bc4d2-ab2c4d2-a2c5d2-c7d2+2a2b3d4+2a2bc2d4-2bc4d4-a2b2d5-a2bcd5+ab2cd5-4b3cd5+2a2c2d5-3abc2d5+b2c2d5-bc3d5+2c4d5+2a3d6+2ab2d6+2ac2d6-2a2d7+4abd7+b2d7-3bcd7+c2d7+6d9\n\ 11 b2c2<2> ab2c4d2+a2c5d2-abc5d2+bc6d2+c7d2+ab2c3d3-b2c4d3-bc5d3-2a2b3d4+2a3bcd4-a3c2d4-2a2bc2d4-ab2c2d4-ac4d4+2bc4d4+a2b2d5+a2bcd5+2ab2cd5+4b3cd5-a2c2d5+abc2d5+bc3d5-c4d5-2a3d6-2ab2d6-2ac2d6+2a2d7-4abd7-b2d7+3acd7+3bcd7-4c2d7+3cd8-6d9\n\ 12 ab3<1> a3c4d2+b2c5d2+ac6d2+bc6d2-a3bcd4-ab3cd4-a3c2d4-ab2c2d4+abc3d4-ac4d4-a3bd5+2ab3d5-2a3cd5+3a2bcd5-2ab2cd5-abc2d5-2ac3d5-2a2d7+3abd7-2b2d7-3bcd7-5c2d7\n\ 13 b3c<2> a2c5d2-abc5d2+b2c5d2+2bc6d2+c7d2-b3c3d3-a2c4d3-2b2c4d3-bc5d3-c6d3-2a2b3d4+a3bcd4-ab3cd4-2a3c2d4-2a2bc2d4-2ab2c2d4+abc3d4-2ac4d4+2bc4d4-a2b2d5+3ab3d5+2a2bcd5+5b3cd5-a2c2d5+abc2d5+2bc3d5-c4d5-2a3d6+a2bd6-2ab2d6-2b3d6+2a2cd6-3abcd6+2b2cd6-2ac2d6+bc2d6+2c3d6-abd7-3b2d7+3acd7-9c2d7+3cd8-6d9\n\ 14 a2b2<1> a3bc5+b2c7+2b2c5d2-2a3bc2d3-2ab2c3d3-2b3c3d3-2abc4d3+2bc5d3+4a2b3d4-6a3bcd4-2ab3cd4+4a2bc2d4+2abc3d4-4a2b2d5+6ab3d5-3a3cd5+2a2bcd5-9ab2cd5-4b3cd5-a2c2d5+4abc2d5-2b2c2d5-7bc3d5-c4d5+a2cd6+b2cd6+c3d6-9a2d7+16abd7-3b2d7-6acd7-6bcd7-3c2d7-3ad8+6bd8-6cd8\n\ 15 ab3<2> a3bd5-ac3d5-b3d6-abcd6+2ad8\n\ 16 ab2c2<2> b2c6d2-bc7d2+abc5d3+b2c5d3-a3bc2d4+3ab2c3d4+a2c4d4+abc4d4+2b2c4d4-2bc5d4+c6d4-a2b3d5-2a3bcd5-ab3cd5-6ab2c2d5-3b3c2d5-abc3d5+2b2c3d5-2bc4d5+2a2b2d6-2ab3d6+2a3cd6+2ab2cd6-2abc2d6-4ac3d6+2a3d7-a2bd7-3ab2d7-5b3d7-7a2cd7+7abcd7-4b2cd7+2ac2d7-5bc2d7-c3d7+a2d8+b2d8-3acd8+c2d8+6ad9-3bd9+6cd9\n\ 17 a2b3<1> abc6d2+bc7d2-2b2c5d3-bc6d3-ab2c3d4+b3c3d4+a2c4d4+2abc4d4-b2c4d4+c6d4+4a2b3d5+4a3bcd5+5ab3cd5+a3c2d5+2ab2c2d5+3b3c2d5-a2c3d5-abc3d5-b2c3d5-2ac4d5+3bc4d5-c5d5+2a2b2d6-ab3d6-a2bcd6+2ab2cd6-4b3cd6-abc2d6+2ac3d6-bc3d6-2a3d7-3ab2d7+5b3d7-a2cd7+2abcd7-4b2cd7-2ac2d7-7c3d7+2a2d8-b2d8+6acd8+3bcd8+5c2d8-4ad9+6bd9-3d10\n\ 18 a2b3<2> a2b3d5+a2bc2d5+a2c3d5+ab3d6-b3cd6-bc3d6-2a2d8+3abd8\n\ 19 bc5<2> a2bc6d2-ab2c6d2+b2c7d2+2abc5d4+2b2c5d4-4bc6d4-5ab2c3d5-2b3c3d5-a2c4d5+b2c4d5+4bc5d5-c6d5-4ab3cd6+3a3c2d6+a2bc2d6+6ab2c2d6+3b3c2d6-3abc3d6+b2c3d6-4ac4d6+2bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-8ab2cd7-5b3cd7-6a2c2d7+5abc2d7-4b2c2d7-3ac3d7-bc3d7-3c4d7-3a3d8+3a2bd8-ab2d8-5b3d8+6a2cd8-11abcd8+3b2cd8-3ac2d8+3c3d8+a2d9-2abd9-b2d9+8acd9-9bcd9+11c2d9+ad10-15cd10\n\ 20 b3c3<1> a2c7d2+b2c7d2+c9d2-4ab2c3d5+2b3c3d5-3a2c4d5+4abc4d5-2b2c4d5+3bc5d5-3c6d5-2ab3cd6-a3c2d6+a2bc2d6+ab2c2d6+3b3c2d6-abc3d6+2b2c3d6-2ac4d6+3bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-2ab2cd7+b3cd7-2a2c2d7+3abc2d7-3b2c2d7-5ac3d7+2bc3d7-2c4d7-3a3d8+3a2bd8-4ab2d8-7b3d8+5a2cd8-11abcd8+2b2cd8-3ac2d8+2c3d8+a2d9-2abd9-b2d9+2acd9-3bcd9-c2d9+2ad10-9cd10-3d11\n\ 21 b3c3<2> abc7d2-2bc8d2-abc5d4+2b2c5d4-3bc6d4+2a3bc2d5-7ab2c3d5-4b3c3d5-2a2c4d5+abc4d5-2b2c4d5+3bc5d5-2c6d5-3ab3cd6+3a3c2d6-a2bc2d6+12ab2c2d6+b3c2d6+2a2c3d6-2b2c3d6+3ac4d6+6ab3d7+2a3cd7-6a2bcd7-4ab2cd7+2b3cd7-4a2c2d7+9abc2d7-2b2c2d7+ac3d7+2bc3d7+5c4d7+a2bd8+2b3d8+9a2cd8-14abcd8+9b2cd8+6bc2d8+6c3d8-2a2d9-2abd9+2b2d9+3acd9-9bcd9+8c2d9-ad10+3bd10-15cd10+3d11\n\ 22 a2b3c<1> bc8d2-bc7d3-2526abc5d4-b2c5d4+2531ab2c3d5+3b3c3d5+4b2c4d5-ac5d5-bc5d5+ab3cd6+a2bc2d6-6ab2c2d6-4b3c2d6-2528a2c3d6-2529abc3d6+2b2c3d6-2bc4d6-a2b2d7-2534ab3d7+a2bcd7+2530ab2cd7-2b3cd7+2529a2c2d7-6abc2d7+2527b2c2d7-5ac3d7-2bc3d7+2524c4d7+2a3d8-2ab2d8-7b3d8-5a2cd8+5abcd8-4b2cd8+4ac2d8-3bc2d8+c3d8+a2d9+abd9+2530b2d9-3acd9+6bcd9+2530c2d9+7ad10-12bd10+7cd10\n\ 23 a3b3<1> a2c4d5+abc4d5+b2c4d5-bc5d5+ab3cd6-ab2c2d6-b3c2d6+b2c3d6-ab3d7+a3cd7+ab2cd7-abc2d7-2ac3d7-3ab2d8-3b3d8-3a2cd8+2abcd8-b2cd8-c3d8+3ad10-3bd10+3cd10-3d11\n\ 24 abc5<2> abc8d2-2bc9d2+abc5d5-11b2c5d5-3bc6d5+12ab2c3d6+7b3c3d6-8abc4d6-11b2c4d6+2ac5d6+12bc5d6+7c6d6+12ab3cd7+8a3c2d7-9a2bc2d7+21ab2c2d7+19b3c2d7-8a2c3d7+3abc3d7-17b2c3d7+9ac4d7+16bc4d7+4c5d7+10a2b2d8-6ab3d8-14a3cd8-3a2bcd8-4ab2cd8+5b3cd8+7a2c2d8+9abc2d8+9b2c2d8+29ac3d8+bc3d8+4c4d8-4a3d9-20a2bd9+29ab2d9+63b3d9+23a2cd9-8abcd9-5ac2d9-4bc2d9-3c3d9+18a2d10-20abd10-3b2d10-11acd10+27bcd10+15c2d10-50ad11+48bd11-33cd11+3d12\n\ 25 ab3c3<2> ac6d5+bc6d5+b3c3d6-b2c4d6-a3c2d7-ab2c2d7+2a2c3d7+ac4d7+3a2b2d8+2ab3d8+3ab2cd8+2b3cd8-2ac3d8-a2d10-acd10-3c2d10+3ad11\n\ 26 a3b3c<1> abc5d5+3790bc6d5+3791c7d5-ab2c3d6-3790b2c4d6+3792bc5d6-3790a3c2d7-3790ab2c2d7-a2c3d7-abc3d7+3791ac4d7-bc4d7+3791a2b2d8+3789ab3d8-a2bcd8+3790ab2cd8+3788b3cd8-a2c2d8+3791b2c2d8+a3d9+ab2d9+ac2d9+2a2d10+3789abd10-3790b2d10+acd10+3790bcd10+6c2d10+3790bd11-3cd11+3d12\n\ 27 a2bc5<2> bc10d2+2540bc7d5+2521b2c5d6-2535bc6d6-846c7d6+2511ab2c3d7+2523b3c3d7+2509abc4d7-17b2c4d7+3ac5d7+852bc5d7-2525c6d7+3ab3cd8+2534a3c2d8-2536a2bc2d8+2570ab2c2d8+2569b3c2d8+1669a2c3d8-3371abc3d8-2554b2c3d8-3372ac4d8-1668bc4d8-3c5d8-3357a2b2d9-841ab3d9-2548a3cd9+856a2bcd9+1663ab2cd9+1675b3cd9+2518a2c2d9+2566abc2d9+845b2c2d9-2473ac3d9+2538bc3d9+1688c4d9-3392a3d10-2530a2bd10-792ab2d10+85b3d10+40a2cd10+2517abcd10+2536b2cd10-3395ac2d10+2528bc2d10-2559c3d10-1654a2d11+793abd11-855b2d11-830acd11-2537bcd11-819c2d11-75ad12-2444bd12-53cd12-2507d13\n\ 28 a2b3c3<1> ac7d5+bc7d5-b2c5d6+3790bc6d6+3791c7d6-ab2c3d7-2abc4d7+3791b2c4d7+2ac5d7-3789bc5d7-ab3cd8-3790a3c2d8-a2bc2d8-3784ab2c2d8+5b3c2d8-2a2c3d8-2b2c3d8+3791ac4d8+bc4d8+3791a2b2d9+3790ab3d9-2a3cd9-a2bcd9+3788ab2cd9+3791b3cd9-a2c2d9+4abc2d9+3791b2c2d9+4ac3d9+bc3d9-4a3d10+4a2bd10+4ab2d10+5b3d10+5a2cd10-4abcd10+2b2cd10-5ac2d10-bc2d10-c3d10+3a2d11+3786abd11-3788b2d11+3acd11+3790bcd11+5c2d11-6ad12-3787bd12-9cd12+3d13\n\ 29 a3b3c2<1> bc7d5-3033c8d5-b2c5d6+3033bc6d6-3034ab2c3d7+3034abc4d7+3032b2c4d7+3034ac5d7+3034bc5d7-1515ab3cd8-3035a2bc2d8+1518ab2c2d8-1513b3c2d8+3031a2c3d8+1516b2c3d8+1518bc4d8-1517c5d8-ab3d9-3034a3cd9-3034ab2cd9-3031b3cd9-3032abc2d9-3032ac3d9-3031bc3d9+3031a3d10-1515a2bd10+3033ab2d10+3035b3d10+3034a2cd10+3033abcd10-b2cd10+1514ac2d10+1517bc2d10-4c3d10+1521a2d11-1522abd11+3032b2d11-1516bcd11-3032c2d11-3036ad12-1513bd12-1519cd12+1516d13\n\ 30 a3b3c3<1> c9d5-3033c8d6-b2c5d7+3030bc6d7+2528c7d7-3032ab2c3d8+3b3c3d8+3040abc4d8+3036b2c4d8+3034ac5d8+507bc5d8-c6d8-1516ab3cd9+3a3c2d9-3035a2bc2d9+1520ab2c2d9-1512b3c2d9-2025a2c3d9+2527abc3d9+1517b2c3d9+2528ac4d9-1007bc4d9-1517c5d9+2523a2b2d10+2525ab3d10-3034a3cd10-2528a2bcd10-511ab2cd10-505b3cd10-2a2c2d10-3029abc2d10-2529b2c2d10-3043ac3d10-3028bc3d10+2526c4d10-2025a3d11-1516a2bd11-2031ab2d11+3025b3d11+3033a2cd11+3024abcd11-3542ac2d11+1514bc2d11-c3d11-1006a2d12+3533abd12-2023b2d12+2529acd12-1515bcd12-495c2d12-3032ad13-1521bd13-1522cd13+1511d14\n\ "; const char* weispfennig97_syzygies_strat0_free4 = " 1: b4 a4b3 \n 2: b4 a2b2c a3b3 b3c4 a3bc5 \n"; const char* weispfennig97_initial_strat0_free4 = " b4\n a2b2c\n a3b2\n a4d2\n b3c4\n ab3c3\n a2bc3d2\n a3c3d2\n ab3c2d2\n a3bc4\n a3bd5\n a2c5d2\n ab2c4d2\n a2b3d5\n b2c6d2\n abc6d2\n a2c4d5\n bc8d2\n ac6d5\n abc5d5\n bc7d5\n c9d5\n"; const char* weispfennig97_gb_strat0_free5 = "\ 0 <0> b4+ab2c+a2d2-2abd2+b2d2+c2d2\n\ 1 <1> a2b2c-bc4+a3d2+ab2d2+ac2d2+3d5\n\ 2 <2> a3b2-abc3+a2d3+b2d3+c2d3\n\ 3 a<1> a4d2+a2b2d2+a2c2d2-a2cd3-b2cd3-c3d3+3ad5\n\ 4 a2c<0> b3c4+abc5-2a3bcd2-ab2c2d2-abc3d2+bc4d2-2a2bd4+a2d5-2b2d5-3acd5+c2d5-3d7\n\ 5 a3<0> ab3c3+a2bc4+2a2b3d2+2a2bc2d2-a2b2d3-2a2bcd3+ab2cd3-2b3cd3-b2c2d3-2bc3d3-2a2d5+4abd5+b2d5+c2d5\n\ 6 a2bc<0> ab3c2d2+ab2c3d2+a2c4d2+c6d2+2a2b2d4-a2bd5+2b3d5-2a2cd5+3abcd5-2b2cd5-bc2d5-2c3d5+3bd7\n\ 7 ab2<1> a2bc3d2-abc4d2+bc5d2+ab2c2d3-b2c3d3-bc4d3+2a3bd4-a3cd4-ab2cd4-ac3d4+3ab2d5+a2cd5-2abcd5+b2cd5+c3d5+3ad7-3cd7+3d8\n\ 8 a3b<0> a3c3d2+ab2c3d2+ac5d2+a2b3d3-ab3cd3+b3c2d3-2a3d5+2a2bd5-b3d5-2ac2d5-bc2d5\n\ 9 a4<0> a3bc4+b2c6+a3bc2d2+3ab2c3d2+a2c4d2-abc4d2+c6d2-2a3bcd3-2ab3cd3-ab2c2d3-3abc3d3+bc4d3+2a2b2d4-3a3d5+a2bd5-2a2cd5+3abcd5-2b2cd5-6bc2d5-2c3d5+a2d6+b2d6+c2d6+3bd7-3d8\n\ 10 a2bc2<0> a2bc4d2-ab2c4d2-a2c5d2-c7d2+2a2b3d4+2a2bc2d4-2bc4d4-a2b2d5-a2bcd5+ab2cd5-4b3cd5+2a2c2d5-3abc2d5+b2c2d5-bc3d5+2c4d5+2a3d6+2ab2d6+2ac2d6-2a2d7+4abd7+b2d7-3bcd7+c2d7+6d9\n\ 11 ab2c<1> ab2c4d2+a2c5d2-abc5d2+bc6d2+c7d2+ab2c3d3-b2c4d3-bc5d3-2a2b3d4+2a3bcd4-a3c2d4-2a2bc2d4-ab2c2d4-ac4d4+2bc4d4+a2b2d5+a2bcd5+2ab2cd5+4b3cd5-a2c2d5+abc2d5+bc3d5-c4d5-2a3d6-2ab2d6-2ac2d6+2a2d7-4abd7-b2d7+3acd7+3bcd7-4c2d7+3cd8-6d9\n\ 12 ab3<1> a2c5d2-abc5d2+b2c5d2+2bc6d2+c7d2-b3c3d3-a2c4d3-2b2c4d3-bc5d3-c6d3-2a2b3d4+a3bcd4-ab3cd4-2a3c2d4-2a2bc2d4-2ab2c2d4+abc3d4-2ac4d4+2bc4d4-a2b2d5+3ab3d5+2a2bcd5+5b3cd5-a2c2d5+abc2d5+2bc3d5-c4d5-2a3d6+a2bd6-2ab2d6-2b3d6+2a2cd6-3abcd6+2b2cd6-2ac2d6+bc2d6+2c3d6-abd7-3b2d7+3acd7-9c2d7+3cd8-6d9\n\ 13 a4b<0> a3bd5-ac3d5-b3d6-abcd6+2ad8\n\ 14 a2b2c<1> b2c6d2-bc7d2+abc5d3+b2c5d3-a3bc2d4+3ab2c3d4+a2c4d4+abc4d4+2b2c4d4-2bc5d4+c6d4-a2b3d5-2a3bcd5-ab3cd5-6ab2c2d5-3b3c2d5-abc3d5+2b2c3d5-2bc4d5+2a2b2d6-2ab3d6+2a3cd6+2ab2cd6-2abc2d6-4ac3d6+2a3d7-a2bd7-3ab2d7-5b3d7-7a2cd7+7abcd7-4b2cd7+2ac2d7-5bc2d7-c3d7+a2d8+b2d8-3acd8+c2d8+6ad9-3bd9+6cd9\n\ 15 a2b3<1> abc6d2+bc7d2-2b2c5d3-bc6d3-ab2c3d4+b3c3d4+a2c4d4+2abc4d4-b2c4d4+c6d4+4a2b3d5+a3bcd5+5ab3cd5+a3c2d5+2ab2c2d5+3b3c2d5-a2c3d5-abc3d5-b2c3d5+ac4d5+3bc4d5-c5d5+2a2b2d6-ab3d6-a2bcd6+2ab2cd6-b3cd6+2abc2d6+2ac3d6-bc3d6-2a3d7-3ab2d7+5b3d7-a2cd7+2abcd7-4b2cd7-2ac2d7-7c3d7+2a2d8-b2d8+3bcd8+5c2d8-4ad9+6bd9-3d10\n\ 16 a5b<0> a2b3d5+a2bc2d5+a2c3d5+ab3d6-b3cd6-bc3d6-2a2d8+3abd8\n\ 17 abc4<1> a2bc6d2-ab2c6d2+b2c7d2+2abc5d4+2b2c5d4-4bc6d4-5ab2c3d5-2b3c3d5-a2c4d5+b2c4d5+4bc5d5-c6d5-4ab3cd6+3a3c2d6+a2bc2d6+6ab2c2d6+3b3c2d6-3abc3d6+b2c3d6-4ac4d6+2bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-8ab2cd7-5b3cd7-6a2c2d7+5abc2d7-4b2c2d7-3ac3d7-bc3d7-3c4d7-3a3d8+3a2bd8-ab2d8-5b3d8+6a2cd8-11abcd8+3b2cd8-3ac2d8+3c3d8+a2d9-2abd9-b2d9+8acd9-9bcd9+11c2d9+ad10-15cd10\n\ 18 a2bc4<0> a2c7d2+b2c7d2+c9d2-4ab2c3d5+2b3c3d5-3a2c4d5+4abc4d5-2b2c4d5+3bc5d5-3c6d5-2ab3cd6-a3c2d6+a2bc2d6+ab2c2d6+3b3c2d6-abc3d6+2b2c3d6-2ac4d6+3bc4d6+c5d6-3a2b2d7+4ab3d7-a3cd7-3a2bcd7-2ab2cd7+b3cd7-2a2c2d7+3abc2d7-3b2c2d7-5ac3d7+2bc3d7-2c4d7-3a3d8+3a2bd8-4ab2d8-7b3d8+5a2cd8-11abcd8+2b2cd8-3ac2d8+2c3d8+a2d9-2abd9-b2d9+2acd9-3bcd9-c2d9+2ad10-9cd10-3d11\n\ 19 ab3c2<1> abc7d2-2bc8d2-abc5d4+2b2c5d4-3bc6d4+2a3bc2d5-7ab2c3d5-4b3c3d5-2a2c4d5+abc4d5-2b2c4d5+3bc5d5-2c6d5-3ab3cd6+3a3c2d6-a2bc2d6+12ab2c2d6+b3c2d6+2a2c3d6-2b2c3d6+3ac4d6+6ab3d7+2a3cd7-6a2bcd7-4ab2cd7+2b3cd7-4a2c2d7+9abc2d7-2b2c2d7+ac3d7+2bc3d7+5c4d7+a2bd8+2b3d8+9a2cd8-14abcd8+9b2cd8+6bc2d8+6c3d8-2a2d9-2abd9+2b2d9+3acd9-9bcd9+8c2d9-ad10+3bd10-15cd10+3d11\n\ 20 a2b3c<1> bc8d2-bc7d3-2526abc5d4-b2c5d4-a3bc2d5+2531ab2c3d5+3b3c3d5+4b2c4d5-bc5d5+ab3cd6+a2bc2d6-6ab2c2d6-3b3c2d6-2528a2c3d6-2528abc3d6+2b2c3d6-2bc4d6-a2b2d7-2534ab3d7+a2bcd7+2530ab2cd7-2b3cd7+2529a2c2d7-6abc2d7+2527b2c2d7-5ac3d7-2bc3d7+2524c4d7+2a3d8-2ab2d8-7b3d8-5a2cd8+5abcd8-4b2cd8+2ac2d8-3bc2d8+c3d8+a2d9+abd9+2530b2d9-3acd9+6bcd9+2530c2d9+7ad10-12bd10+7cd10\n\ 21 a5bc<0> a2c4d5+abc4d5+b2c4d5-bc5d5+ab3cd6-ab2c2d6-b3c2d6+b2c3d6-ab3d7+a3cd7+ab2cd7-abc2d7-2ac3d7-3ab2d8-3b3d8-3a2cd8+2abcd8-b2cd8-c3d8+3ad10-3bd10+3cd10-3d11\n\ 22 a2bc4<1> abc8d2-2bc9d2+abc5d5-11b2c5d5-3bc6d5+12ab2c3d6+7b3c3d6-8abc4d6-11b2c4d6+2ac5d6+12bc5d6+7c6d6+12ab3cd7+8a3c2d7-9a2bc2d7+21ab2c2d7+19b3c2d7-8a2c3d7+3abc3d7-17b2c3d7+9ac4d7+16bc4d7+4c5d7+10a2b2d8-6ab3d8-14a3cd8-3a2bcd8-4ab2cd8+5b3cd8+7a2c2d8+9abc2d8+9b2c2d8+29ac3d8+bc3d8+4c4d8-4a3d9-20a2bd9+29ab2d9+63b3d9+23a2cd9-8abcd9-5ac2d9-4bc2d9-3c3d9+18a2d10-20abd10-3b2d10-11acd10+27bcd10+15c2d10-50ad11+48bd11-33cd11+3d12\n\ 23 a4bc3<0> ac6d5+bc6d5+b3c3d6-b2c4d6-a3c2d7-ab2c2d7+2a2c3d7+ac4d7+3a2b2d8+2ab3d8+3ab2cd8+2b3cd8-2ac3d8-a2d10-acd10-3c2d10+3ad11\n\ 24 a5bc2<0> abc5d5+3790bc6d5+3791c7d5-ab2c3d6-3790b2c4d6+3792bc5d6-3790a3c2d7-3790ab2c2d7-a2c3d7-abc3d7+3791ac4d7-bc4d7+3791a2b2d8+3789ab3d8-a2bcd8+3790ab2cd8+3788b3cd8-a2c2d8+3791b2c2d8+a3d9+ab2d9+ac2d9+2a2d10+3789abd10-3790b2d10+acd10+3790bcd10+6c2d10+3790bd11-3cd11+3d12\n\ 25 a3bc4<1> bc10d2+2540bc7d5+2521b2c5d6-2535bc6d6-846c7d6+2511ab2c3d7+2523b3c3d7+2509abc4d7-17b2c4d7+3ac5d7+852bc5d7-2525c6d7+3ab3cd8+2534a3c2d8-2536a2bc2d8+2570ab2c2d8+2569b3c2d8+1669a2c3d8-3371abc3d8-2554b2c3d8-3372ac4d8-1668bc4d8-3c5d8-3357a2b2d9-841ab3d9-2548a3cd9+856a2bcd9+1663ab2cd9+1675b3cd9+2518a2c2d9+2566abc2d9+845b2c2d9-2473ac3d9+2538bc3d9+1688c4d9-3392a3d10-2530a2bd10-792ab2d10+85b3d10+40a2cd10+2517abcd10+2536b2cd10-3395ac2d10+2528bc2d10-2559c3d10-1654a2d11+793abd11-855b2d11-830acd11-2537bcd11-819c2d11-75ad12-2444bd12-53cd12-2507d13\n\ 26 a5bc3<0> bc7d5-3033c8d5-b2c5d6+3033bc6d6-3034ab2c3d7+3034abc4d7+3032b2c4d7+3034ac5d7+3034bc5d7-1515ab3cd8-3035a2bc2d8+1518ab2c2d8-1513b3c2d8+3031a2c3d8+1516b2c3d8+1518bc4d8-1517c5d8-ab3d9-3034a3cd9-3034ab2cd9-3031b3cd9-3032abc2d9-3032ac3d9-3031bc3d9+3031a3d10-1515a2bd10+3033ab2d10+3035b3d10+3034a2cd10+3033abcd10-b2cd10+1514ac2d10+1517bc2d10-4c3d10+1521a2d11-1522abd11+3032b2d11-1516bcd11-3032c2d11-3036ad12-1513bd12-1519cd12+1516d13\n\ 27 a5bc4<0> c9d5-3033c8d6-b2c5d7+3030bc6d7+2528c7d7-3032ab2c3d8+3b3c3d8+3040abc4d8+3036b2c4d8+3034ac5d8+507bc5d8-c6d8-1516ab3cd9+3a3c2d9-3035a2bc2d9+1520ab2c2d9-1512b3c2d9-2025a2c3d9+2527abc3d9+1517b2c3d9+2528ac4d9-1007bc4d9-1517c5d9+2523a2b2d10+2525ab3d10-3034a3cd10-2528a2bcd10-511ab2cd10-505b3cd10-2a2c2d10-3029abc2d10-2529b2c2d10-3043ac3d10-3028bc3d10+2526c4d10-2025a3d11-1516a2bd11-2031ab2d11+3025b3d11+3033a2cd11+3024abcd11-3542ac2d11+1514bc2d11-c3d11-1006a2d12+3533abd12-2023b2d12+2529acd12-1515bcd12-495c2d12-3032ad13-1521bd13-1522cd13+1511d14\n\ "; const char* weispfennig97_syzygies_strat0_free5 = " 0: a2b2c a3b2 a6b \n 1: ab4 a3b2 ab3c3 a4bc4 \n"; const char* weispfennig97_initial_strat0_free5 = " b4\n a2b2c\n a3b2\n a4d2\n b3c4\n ab3c3\n a2bc3d2\n a3c3d2\n ab3c2d2\n a3bc4\n a3bd5\n a2c5d2\n ab2c4d2\n a2b3d5\n b2c6d2\n abc6d2\n a2c4d5\n bc8d2\n ac6d5\n abc5d5\n bc7d5\n c9d5\n"; const char* Gert93RawIdeal = "3\n" "ab-b2-4bc+ae\n" "a2c-6bc2+a2f\n" "a3+b2c-a2d\n"; std::string gerdt93IdealComponentLast(bool componentsAscending, bool schreyer) { std::ostringstream out; out << "7583 6\n"; if (schreyer) out << "schreyer "; out << "revlex 1\n"; if (componentsAscending) out << " 1 1 1 1 1 1 _revlex component\n"; else out << " 1 1 1 1 1 1 _revlex revcomponent\n"; out << Gert93RawIdeal; return out.str(); } std::string gerdt93IdealComponentFirst(bool componentsAscending) { std::ostringstream out; out << "7583 6 schreyer revlex 2\n"; if (componentsAscending) out << " component\n 1 1 1 1 1 1\n"; else out << " revcomponent\n 1 1 1 1 1 1\n"; out << Gert93RawIdeal; return out.str(); } std::string gerdt93IdealComponentMiddle(bool componentsAscending) { std::ostringstream out; out << "7583 6 schreyer revlex 2\n"; if (componentsAscending) out << "1 1 1 1 1 1\n component\n"; else out << "1 1 1 1 1 1\n revcomponent\n"; out << Gert93RawIdeal; return out.str(); } const char* gerdt93_gb_strat0_free1 = "\ 0 <0> ab-b2-4bc+ae\n\ 1 <1> a2c-6bc2+a2f\n\ 2 <2> a3+b2c-a2d\n\ 3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\ 4 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\ 5 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\ 6 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\ 7 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\ 8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\ 9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\ 10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\ "; const char* gerdt93_syzygies_strat0_free1 = "\ 0: a2c a3 b2c2 abc2 \n\ 1: a3 \n\ "; const char* gerdt93_initial_strat0_free1 = " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n"; const char* gerdt93_gb_strat0_free2 = "\ 0 <0> ab-b2-4bc+ae\n\ 1 <1> a2c-6bc2+a2f\n\ 2 <2> a3+b2c-a2d\n\ 3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\ 4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\ 5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\ 6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\ 7 ac<2> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\ 8 ac2<2> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\ "; const char* gerdt93_syzygies_strat0_free2 = "\ 1: ab \n\ 2: ab b2c a2c \n\ "; const char* gerdt93_initial_strat0_free2 = " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n"; const char* gerdt93_gb_strat0_free3 = "\ 0 <0> ab-b2-4bc+ae\n\ 1 <1> a2c-6bc2+a2f\n\ 2 <2> a3+b2c-a2d\n\ 3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\ 4 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\ 5 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\ 6 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\ 7 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\ 8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\ 9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\ 10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\ "; const char* gerdt93_syzygies_strat0_free3 = "\ 0: a2c a3 b2c2 abc2 \n\ 1: a3 \n\ "; const char* gerdt93_initial_strat0_free3 = " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n"; const char* gerdt93_gb_strat0_free4 = "\ 0 <0> ab-b2-4bc+ae\n\ 1 <1> a2c-6bc2+a2f\n\ 2 <2> a3+b2c-a2d\n\ 3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\ 4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\ 5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\ 6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\ 7 ac<2> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\ 8 ac2<2> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\ "; const char* gerdt93_syzygies_strat0_free4 = "\ 1: ab \n\ 2: ab b2c a2c \n\ "; const char* gerdt93_initial_strat0_free4 = " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n"; const char* gerdt93_gb_strat0_free5 = "\ 0 <0> ab-b2-4bc+ae\n\ 1 <1> a2c-6bc2+a2f\n\ 2 <2> a3+b2c-a2d\n\ 3 ac<0> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\ 4 a<1> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\ 5 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\ 6 ab<1> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\ 7 a2<1> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\ 8 a2c<1> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\ "; const char* gerdt93_syzygies_strat0_free5 = "\ 0: a2c a3 \n\ 1: ab2 a2b a3 \n\ "; const char* gerdt93_initial_strat0_free5 = " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n"; const char* gerdt93_gb_strat0_free6 = "0 <0> ab-b2-4bc+ae\n1 <1> a2c-6bc2+a2f\n2 <2> a3+b2c-a2d\n3 b<1> b3c+2b2c2+16bc3-b2ce-4ac2e-10bc2e+ace2+b3f+8b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n4 c<2> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n5 b<2> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n6 bc<2> bc4-563bc3d-2577bc2d2-1896ac3e-2681bc3e-2577ac2de-3362bc2de+3088ac2e2-1829bc3f-3362b2cdf-2179bc2df-3362b2cef+2353ac2ef+1659bc2ef-1133ace2f-785b3f2+2930b2cf2+2606bc2f2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n7 ac<2> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n8 ac2<2> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n"; const char* gerdt93_syzygies_strat0_free6 = " 1: ab \n 2: ab b2c a2c \n"; const char* gerdt93_initial_strat0_free6 = " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n"; const char* gerdt93_gb_strat0_free7 = "\ 0 <0> ab-b2-4bc+ae\n\ 1 <1> a2c-6bc2+a2f\n\ 2 <2> a3+b2c-a2d\n\ 3 a<1> abc2+1264b2c2-bc2d+1264b2cf\n\ 4 a2<1> b3c2-216b2c3-12b2c2d+36bc2d2-6ab2cf+b3cf+216b2c2f-6b2cdf-36a2bf2\n\ 5 c2<0> b2c2+2170bc3+3249bc2d+3249ac2e+3250b2cf\n\ 6 ac<0> b3c+3259bc3+1085bc2d-b2ce+1081ac2e-10bc2e+ace2+b3f+1091b2cf+16bc2f-b2ef-4acef-4bcef+ae2f\n\ 7 a2<0> b4-2386bc3-b3d-8b2cd-3247bc2d-2b3e-6b2ce-3195ac2e+58bc2e+b2de+4acde+4bcde+a2e2+2b2e2-ace2+8bce2-ade2-2ae3-13b3f-3357b2cf-208bc2f+4a2ef+13b2ef+52acef+52bcef-13ae2f\n\ 8 bc2<0> bc4-563bc3d-2577bc2d2-1896ac3e-469bc3e-2229ac2de+3088bc2de+2013ac2e2-1829bc3f-3362b2cdf-2179bc2df+3088b2cef+2353ac2ef+3515bc2ef-1075ace2f-785b3f2+2930b2cf2+2606bc2f2-348a2ef2+785b2ef2+3140acef2+3140bcef2-785ae2f2\n\ 9 ac2<0> bc3e-3140ac2de-1718bc2de+2814ac2e2-1718b2cef+947bc2ef-3051ace2f+3140a2ef2\n\ 10 ac3<0> ac3de+1155ac2d2e-2873bc2d2e+3790ac3e2-1570ac2de2+3362bc2de2-3088ac2e3+2814b2cdef+2370bc2def+3362b2ce2f-3790ac2e2f-1659bc2e2f-3599acde2f+1133ace3f-1896b3ef2-1898b2cef2-10bc2ef2-1155a2def2+2681a2e2f2+1896b2e2f2+ace2f2+bce2f2-1896ae3f2+a2ef3\n\ "; const char* gerdt93_syzygies_strat0_free7 = " 0: a2c a3 b2c2 abc2 \n 1: a3 \n"; const char* gerdt93_initial_strat0_free7 = " ab\n a2c\n a3\n b2c2\n b3c\n b4\n bc3e\n bc4\n ac3de\n"; mathicgb-master/src/test/ideals.hpp000077500000000000000000000043251311555162500176600ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #ifndef MATHICGB_IDEALS_GUARD #define MATHICGB_IDEALS_GUARD #include namespace mgb {} // small std::string smallIdealComponentLastDescending(); extern const char* idealSmallBasis; extern const char* idealSmallSyzygies; extern const char* idealSmallInitial; // liu std::string liuIdealComponentLastDescending(); extern const char* liu_gb_strat0_free1; extern const char* liu_syzygies_strat0_free1; extern const char* liu_initial_strat0_free1; // weispfennig97 std::string weispfennig97IdealComponentLast(bool componentsAscending); extern const char* weispfennig97_gb_strat0_free4; extern const char* weispfennig97_syzygies_strat0_free4; extern const char* weispfennig97_initial_strat0_free4; extern const char* weispfennig97_gb_strat0_free5; extern const char* weispfennig97_syzygies_strat0_free5; extern const char* weispfennig97_initial_strat0_free5; // gerdt93 std::string gerdt93IdealComponentFirst(bool componentsAscending); std::string gerdt93IdealComponentMiddle(bool componentsAscending); std::string gerdt93IdealComponentLast(bool componentsAscending, bool schreyer); extern const char* gerdt93_gb_strat0_free1; extern const char* gerdt93_syzygies_strat0_free1; extern const char* gerdt93_initial_strat0_free1; extern const char* gerdt93_gb_strat0_free2; extern const char* gerdt93_syzygies_strat0_free2; extern const char* gerdt93_initial_strat0_free2; extern const char* gerdt93_gb_strat0_free3; extern const char* gerdt93_syzygies_strat0_free3; extern const char* gerdt93_initial_strat0_free3; extern const char* gerdt93_gb_strat0_free4; extern const char* gerdt93_syzygies_strat0_free4; extern const char* gerdt93_initial_strat0_free4; extern const char* gerdt93_gb_strat0_free5; extern const char* gerdt93_syzygies_strat0_free5; extern const char* gerdt93_initial_strat0_free5; extern const char* gerdt93_gb_strat0_free6; extern const char* gerdt93_syzygies_strat0_free6; extern const char* gerdt93_initial_strat0_free6; extern const char* gerdt93_gb_strat0_free7; extern const char* gerdt93_syzygies_strat0_free7; extern const char* gerdt93_initial_strat0_free7; #endif mathicgb-master/src/test/mathicgb.cpp000077500000000000000000000717451311555162500202020ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb.h" #include using namespace mgb; namespace { template void makeBasis(Stream& s) { MATHICGB_ASSERT(s.varCount() >= 3); MATHICGB_ASSERT(s.comCount() >= 1); s.idealBegin(); s.appendPolynomialBegin(); // x^2 - y s.appendTermBegin(0); s.appendExponent(0,2); s.appendTermDone(1); s.appendTermBegin(0); s.appendExponent(1,1); s.appendTermDone(s.modulus() - 1); s.appendPolynomialDone(); s.appendPolynomialBegin(2); // x^3-z s.appendTermBegin(0); s.appendExponent(0,3); s.appendTermDone(1); s.appendTermBegin(0); s.appendExponent(2,1); s.appendTermDone(s.modulus() - 1); s.appendPolynomialDone(); s.idealDone(); } template void makeGroebnerBasis(Stream& s) { s.idealBegin(3); s.appendPolynomialBegin(2); // x^2 - y s.appendTermBegin(0); s.appendExponent(0, 2); s.appendExponent(1, 0); s.appendExponent(2, 0); s.appendTermDone(1); s.appendTermBegin(0); s.appendExponent(0, 0); s.appendExponent(1, 1); s.appendExponent(2, 0); s.appendTermDone(s.modulus() - 1); s.appendPolynomialDone(); s.appendPolynomialBegin(2); // xy - z s.appendTermBegin(0); s.appendExponent(0, 1); s.appendExponent(1, 1); s.appendExponent(2, 0); s.appendTermDone(1); s.appendTermBegin(0); s.appendExponent(0, 0); s.appendExponent(1, 0); s.appendExponent(2, 1); s.appendTermDone(s.modulus() - 1); s.appendPolynomialDone(); s.appendPolynomialBegin(2); // y^2 - xz s.appendTermBegin(0); s.appendExponent(0, 0); s.appendExponent(1, 2); s.appendExponent(2, 0); s.appendTermDone(1); s.appendTermBegin(0); s.appendExponent(0, 1); s.appendExponent(1, 0); s.appendExponent(2, 1); s.appendTermDone(s.modulus() - 1); s.appendPolynomialDone(); s.idealDone(); } template void makeCyclic5Basis(Stream& s) { s.idealBegin(5); // polyCount s.appendPolynomialBegin(5); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(1, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(2, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(3, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(5); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(5); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(5); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(2); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.idealDone(); } template void makeSimpleIdeal(Stream& s) { // variables a,b,c,d. a2-bc, ab-cd. s.idealBegin(); s.appendPolynomialBegin(); // a^2-b*c s.appendTermBegin(0); s.appendExponent(0,2); s.appendTermDone(1); s.appendTermBegin(0); s.appendExponent(1,1); s.appendExponent(2,1); s.appendTermDone(s.modulus() - 1); s.appendPolynomialDone(); s.appendPolynomialBegin(2); // a*b-c*d s.appendTermBegin(0); s.appendExponent(0,1); s.appendExponent(1,1); s.appendTermDone(1); s.appendTermBegin(0); s.appendExponent(2,1); s.appendExponent(3,1); s.appendTermDone(s.modulus() - 1); s.appendPolynomialDone(); s.idealDone(); } template void makeSimpleIdealGroebnerBasis(Stream& s) { // variables a,b,c,d. a2-bc, ab-cd. // Groebner basis is {a^2-b*c,a*b-c*d,a*c*d-b^2*c,b^3*c-c^2*d^2} // (order: eliminate 1 variable: [1 0 0 0; 1 1 1 1]). s.idealBegin(4); // polyCount s.appendPolynomialBegin(2); s.appendTermBegin(0); s.appendExponent(0, 2); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(2); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(2); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 2); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(2); s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 3); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 2); // index, exponent s.appendExponent(3, 2); // index, exponent s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.idealDone(); } template void makeSimpleModuleBasis(Stream& s) { MATHICGB_ASSERT(s.varCount() >= 4); MATHICGB_ASSERT(s.comCount() >= 4); // The basis is // c2<0>-b<1>+d<2> // bd<0>-a<1>+c<2> // ac<0>-b<2>-d<3> // b2<0>-a<2>-c<3> const auto minusOne = s.modulus() - 1; s.idealBegin(4); s.appendPolynomialBegin(3); // c2<0>-b<1>+d<2> s.appendTermBegin(0); s.appendExponent(2, 2); s.appendTermDone(1); s.appendTermBegin(1); s.appendExponent(1, 1); s.appendTermDone(minusOne); s.appendTermBegin(2); s.appendExponent(3, 1); s.appendTermDone(1); s.appendPolynomialDone(); s.appendPolynomialBegin(3); // bd<0>-a<1>+c<2> s.appendTermBegin(0); s.appendExponent(1, 1); s.appendExponent(3, 1); s.appendTermDone(1); s.appendTermBegin(1); s.appendExponent(0, 1); s.appendTermDone(minusOne); s.appendTermBegin(2); s.appendExponent(2, 1); s.appendTermDone(1); s.appendPolynomialDone(); s.appendPolynomialBegin(3); // ac<0>-b<2>-d<3> s.appendTermBegin(0); s.appendExponent(0, 1); s.appendExponent(2, 1); s.appendTermDone(1); s.appendTermBegin(2); s.appendExponent(1, 1); s.appendTermDone(minusOne); s.appendTermBegin(3); s.appendExponent(3, 1); s.appendTermDone(minusOne); s.appendPolynomialDone(); s.appendPolynomialBegin(3); // b2<0>-a<2>-c<3> s.appendTermBegin(0); s.appendExponent(1, 2); s.appendTermDone(1); s.appendTermBegin(2); s.appendExponent(0, 1); s.appendTermDone(minusOne); s.appendTermBegin(3); s.appendExponent(2, 1); s.appendTermDone(minusOne); s.appendPolynomialDone(); s.idealDone(); } template void makeSimpleModuleGroebnerBasis(Stream& s) { s.idealBegin(5); // polyCount s.appendPolynomialBegin(3); s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 2); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(1); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendTermBegin(2); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(3); s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(1); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendTermBegin(2); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(3); s.appendTermBegin(0); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(2); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendTermBegin(3); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(3); s.appendTermBegin(0); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 2); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(2); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendTermBegin(3); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.appendPolynomialBegin(4); s.appendTermBegin(1); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(1); // coefficient s.appendTermBegin(2); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 1); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 0); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendTermBegin(2); s.appendExponent(0, 1); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 0); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendTermBegin(3); s.appendExponent(0, 0); // index, exponent s.appendExponent(1, 0); // index, exponent s.appendExponent(2, 1); // index, exponent s.appendExponent(3, 1); // index, exponent s.appendExponent(4, 0); // index, exponent s.appendTermDone(100); // coefficient s.appendPolynomialDone(); s.idealDone(); } } TEST(MathicGBLib, NullIdealStream) { { mgb::NullIdealStream stream(2, 3, 1); ASSERT_EQ(2, stream.modulus()); ASSERT_EQ(3, stream.varCount()); ASSERT_EQ(1, stream.comCount()); makeBasis(stream); } { mgb::NullIdealStream stream(2, 3, 4); ASSERT_EQ(2, stream.modulus()); ASSERT_EQ(3, stream.varCount()); ASSERT_EQ(4, stream.comCount()); makeBasis(stream); } { mgb::NullIdealStream stream(101, 0, 0); ASSERT_EQ(101, stream.modulus()); ASSERT_EQ(0, stream.varCount()); ASSERT_EQ(0, stream.comCount()); } } TEST(MathicGBLib, IdealStreamLog) { { const char* const idealStr = "s.idealBegin();\n" "s.appendPolynomialBegin();\n" "s.appendTermBegin(0);\n" "s.appendExponent(0, 2); // index, exponent\n" "s.appendTermDone(1); // coefficient\n" "s.appendTermBegin(0);\n" "s.appendExponent(1, 1); // index, exponent\n" "s.appendTermDone(6); // coefficient\n" "s.appendPolynomialDone();\n" "s.appendPolynomialBegin(2);\n" "s.appendTermBegin(0);\n" "s.appendExponent(0, 3); // index, exponent\n" "s.appendTermDone(1); // coefficient\n" "s.appendTermBegin(0);\n" "s.appendExponent(2, 1); // index, exponent\n" "s.appendTermDone(6); // coefficient\n" "s.appendPolynomialDone();\n" "s.idealDone();\n"; std::ostringstream out1; mgb::IdealStreamLog<> stream1(out1, 7, 3, 1); mgb::IdealStreamChecker checker(stream1); std::ostringstream out2; mgb::IdealStreamLog stream2(out2, checker); std::ostringstream out3; mgb::IdealStreamLog stream3(out3, stream2); ASSERT_EQ(7, stream1.modulus()); ASSERT_EQ(3, stream1.varCount()); ASSERT_EQ(7, checker.modulus()); ASSERT_EQ(3, checker.varCount()); ASSERT_EQ(7, stream2.modulus()); ASSERT_EQ(3, stream2.varCount()); ASSERT_EQ(7, stream3.modulus()); ASSERT_EQ(3, stream3.varCount()); makeBasis(stream3); const auto str1 = std::string( "IdealStreamLog s(stream, 7, 3, 1);\n" ) + idealStr; ASSERT_EQ(str1, out1.str()) << "Displayed expected:\n" << out1.str() << "Displayed actual:\n" << str1 << std::endl; const auto str2 = std::string( "IdealStreamLog s(stream, log); // modulus=7, varCount=3, comCount=1\n" ) + idealStr; ASSERT_EQ(str2, out2.str()) << "Displayed expected:\n" << out2.str(); ASSERT_EQ(str2, out3.str()) << "Displayed expected:\n" << out3.str(); } // The ideal <> in no variables and no components { std::ostringstream out; mgb::IdealStreamLog<> stream(out, 101, 0, 0); ASSERT_EQ(101, stream.modulus()); ASSERT_EQ(0, stream.varCount()); stream.idealBegin(0); stream.idealDone(); } // The ideal <0> in no variables and no components { std::ostringstream out; mgb::IdealStreamLog<> stream(out, 101, 0, 0); ASSERT_EQ(101, stream.modulus()); ASSERT_EQ(0, stream.varCount()); stream.idealBegin(1); stream.appendPolynomialBegin(0); // 0 stream.appendPolynomialDone(); stream.idealDone(); } // The ideal <1, 0> in no variables and 1 component { std::ostringstream out; mgb::IdealStreamLog<> stream(out, 101, 0, 0); ASSERT_EQ(101, stream.modulus()); ASSERT_EQ(0, stream.varCount()); stream.idealBegin(2); stream.appendPolynomialBegin(0); // 1 stream.appendTermBegin(0); stream.appendTermDone(1); stream.appendPolynomialDone(); stream.appendPolynomialBegin(0); // 0 stream.appendPolynomialDone(); stream.idealDone(); } } TEST(MathicGBLib, ZeroIdealGB) { mgb::GroebnerConfiguration configuration(2, 0, 0); mgb::GroebnerInputIdealStream input(configuration); std::ostringstream out; mgb::IdealStreamLog<> logStream(out, 2, 0, 0); input.idealBegin(0); input.idealDone(); mgb::computeGroebnerBasis(input, logStream); const auto msg = "IdealStreamLog s(stream, 2, 0, 0);\n" "s.idealBegin(0); // polyCount\n" "s.idealDone();\n"; EXPECT_EQ(msg, out.str()); } TEST(MathicGBLib, OneIdealGB) { mgb::GroebnerConfiguration configuration(2, 0, 1); mgb::GroebnerInputIdealStream input(configuration); std::ostringstream out; mgb::IdealStreamLog<> logStream(out, 2, 0, 1); input.idealBegin(1); input.appendPolynomialBegin(1); input.appendTermBegin(0); input.appendTermDone(1); input.appendPolynomialDone(); input.idealDone(); mgb::computeGroebnerBasis(input, logStream); const auto msg = "IdealStreamLog s(stream, 2, 0, 1);\n" "s.idealBegin(1); // polyCount\n" "s.appendPolynomialBegin(1);\n" "s.appendTermBegin(0);\n" "s.appendTermDone(1); // coefficient\n" "s.appendPolynomialDone();\n" "s.idealDone();\n"; EXPECT_EQ(msg, out.str()); } TEST(MathicGBLib, EasyGB) { mgb::GroebnerConfiguration configuration(101, 3, 1); mgb::GroebnerInputIdealStream input(configuration); std::ostringstream computedStr; mgb::IdealStreamLog<> computed(computedStr, 101, 3, 1); mgb::IdealStreamChecker checked(computed); makeBasis(input); mgb::computeGroebnerBasis(input, checked); std::ostringstream correctStr; mgb::IdealStreamLog<> correct(correctStr, 101, 3, 1); mgb::IdealStreamChecker correctChecked(correct); makeGroebnerBasis(correctChecked); EXPECT_EQ(correctStr.str(), computedStr.str()) << "\nDisplayed expected:\n" << correctStr.str() << "\nDisplayed computed:\n" << computedStr.str(); } TEST(MathicGBLib, EasyReGB) { mgb::GroebnerConfiguration configuration(101, 3, 1); mgb::GroebnerInputIdealStream input(configuration); std::ostringstream computedStr; mgb::IdealStreamLog<> computed(computedStr, 101, 3, 1); mgb::IdealStreamChecker checked(computed); makeGroebnerBasis(input); mgb::computeGroebnerBasis(input, checked); std::ostringstream correctStr; mgb::IdealStreamLog<> correct(correctStr, 101, 3, 1); mgb::IdealStreamChecker correctChecked(correct); makeGroebnerBasis(correctChecked); EXPECT_EQ(correctStr.str(), computedStr.str()) << "\nDisplayed expected:\n" << correctStr.str() << "\nDisplayed computed:\n" << computedStr.str(); } TEST(MathicGBLib, Cyclic5) { for (int i = 0; i < 2; ++i) { mgb::GroebnerConfiguration configuration(101, 5, 1); const auto reducer = i == 0 ? mgb::GroebnerConfiguration::ClassicReducer : mgb::GroebnerConfiguration::MatrixReducer; configuration.setReducer(reducer); mgb::GroebnerInputIdealStream input(configuration); makeCyclic5Basis(input); mgb::NullIdealStream computed (input.modulus(), input.varCount(), input.comCount()); mgb::computeGroebnerBasis(input, computed); } } TEST(MathicGBLib, SimpleModuleIdeal) { for (int i = 0; i < 2; ++i) { mgb::GroebnerConfiguration configuration(101, 5, 4); const auto reducer = i == 0 ? mgb::GroebnerConfiguration::ClassicReducer : mgb::GroebnerConfiguration::MatrixReducer; configuration.setReducer(reducer); mgb::GroebnerInputIdealStream input(configuration); std::ostringstream computedStr; mgb::IdealStreamLog<> computed(computedStr, 101, 5, 4); mgb::IdealStreamChecker checked(computed); makeSimpleModuleBasis(input); mgb::computeGroebnerBasis(input, checked); std::ostringstream correctStr; mgb::IdealStreamLog<> correct(correctStr, 101, 5, 4); mgb::IdealStreamChecker correctChecked(correct); makeSimpleModuleGroebnerBasis(correctChecked); EXPECT_EQ(correctStr.str(), computedStr.str()) << "\nDisplayed expected:\n" << correctStr.str() << "\nDisplayed computed:\n" << computedStr.str(); } } namespace { class TestCallback : public mgb::GroebnerConfiguration::Callback { public: TestCallback(int count, Action action): mCount(count), mAction(action) {} virtual Action call() { --mCount; return mCount == 0 ? mAction : ContinueAction; } private: int mCount; const Action mAction; }; } TEST(MathicGBLib, EarlyExit) { typedef mgb::GroebnerConfiguration::Callback::Action Action; auto check = [](bool useClassic, int count, Action action) { mgb::GroebnerConfiguration configuration(101, 5, 1); const auto reducer = useClassic ? mgb::GroebnerConfiguration::ClassicReducer : mgb::GroebnerConfiguration::MatrixReducer; configuration.setReducer(reducer); TestCallback callback(count, action); configuration.setCallback(&callback); mgb::GroebnerInputIdealStream input(configuration); makeCyclic5Basis(input); std::ostringstream strOut; mgb::IdealStreamLog<> out(strOut, 101, 5, 1); mgb::computeGroebnerBasis(input, out); return strOut.str().size(); }; for (int useClassic = 0; useClassic < 2; ++useClassic) { size_t none = check(useClassic, 5, Action::StopWithNoOutputAction); size_t minSize = check(useClassic, 1, Action::StopWithPartialOutputAction); size_t midSize = check(useClassic, 4, Action::StopWithPartialOutputAction); size_t maxSize = check(useClassic, 1, Action::ContinueAction); ASSERT_LT(none, 38u); // the stream writes a header even for no output ASSERT_LT(none, minSize); ASSERT_LT(minSize, midSize); ASSERT_LT(midSize, maxSize); } } TEST(MathicGBLib, SimpleEliminationGB) { typedef mgb::GroebnerConfiguration::Exponent Exponent; Exponent v[] = {1,0,0,0, 1,1,1,1}; std::vector gradings(v, v + sizeof(v)/sizeof(*v)); for (int i = 0; i < 2; ++i) { mgb::GroebnerConfiguration configuration(101, 4, 1); const auto reducer = i == 0 ? mgb::GroebnerConfiguration::ClassicReducer : mgb::GroebnerConfiguration::MatrixReducer; configuration.setReducer(reducer); configuration.setMonomialOrder( mgb::GroebnerConfiguration::BaseOrder::RevLexDescendingBaseOrder, gradings ); mgb::GroebnerInputIdealStream input(configuration); std::ostringstream computedStr; mgb::IdealStreamLog<> computed(computedStr, 101, 4, 1); mgb::IdealStreamChecker checked(computed); makeSimpleIdeal(input); mgb::computeGroebnerBasis(input, checked); std::ostringstream correctStr; mgb::IdealStreamLog<> correct(correctStr, 101, 4, 1); mgb::IdealStreamChecker correctChecked(correct); makeSimpleIdealGroebnerBasis(correctChecked); EXPECT_EQ(correctStr.str(), computedStr.str()) << "\nDisplayed expected:\n" << correctStr.str() << "\nDisplayed computed:\n" << computedStr.str(); #if 0 mgb::GroebnerInputIdealStream input(configuration); makeSimpleIdeal(input); mgb::NullIdealStream computed(input.modulus(), input.varCount()); mgb::computeGroebnerBasis(input, computed); #endif } } TEST(MathicGBLib, GlobalOrderOrNot) { mgb::GroebnerConfiguration conf(101, 4, 1); const auto lex = mgb::GroebnerConfiguration::BaseOrder::LexAscendingBaseOrder; const auto revLex = mgb::GroebnerConfiguration::BaseOrder::RevLexDescendingBaseOrder; typedef mgb::GroebnerConfiguration::Exponent Exponent; std::vector mat; mat.clear(); ASSERT_TRUE(conf.setMonomialOrder(lex, mat)); ASSERT_FALSE(conf.setMonomialOrder(revLex, mat)); Exponent mat2[] = {1,2,3,0}; mat.assign(mat2, mat2 + sizeof(mat2)/sizeof(*mat2)); ASSERT_TRUE(conf.setMonomialOrder(lex, mat)); ASSERT_FALSE(conf.setMonomialOrder(revLex, mat)); Exponent mat3[] = {1,0,0,0, -3,0,1,2}; mat.assign(mat3, mat3 + sizeof(mat3)/sizeof(*mat3)); ASSERT_TRUE(conf.setMonomialOrder(lex, mat)); ASSERT_FALSE(conf.setMonomialOrder(revLex, mat)); Exponent mat4[] = {1,1,0,0, 3,0,1,2}; mat.assign(mat4, mat4 + sizeof(mat4)/sizeof(*mat4)); ASSERT_TRUE(conf.setMonomialOrder(lex, mat)); ASSERT_TRUE(conf.setMonomialOrder(revLex, mat)); Exponent mat5[] = {1,0,0,0, 3,1,1,-2}; mat.assign(mat5, mat5 + sizeof(mat5)/sizeof(*mat5)); ASSERT_FALSE(conf.setMonomialOrder(lex, mat)); ASSERT_FALSE(conf.setMonomialOrder(revLex, mat)); } mathicgb-master/src/test/monoidPict.in000077500000000000000000000015541311555162500203440ustar00rootroot00000000000000# See pict.in for what pict files do. # This file is for getting a good set of test instantiations of MonoMonoid. # See the test file MonoMonoid.cpp. # # To generate a set of test configurations, do # # pict monoidPict.in /e:monoidPict.seed > monoidPict.out # # Then reformat the output and put it into MonoMonoid.cpp as the set # of PolyRing configurations to use. ############################################################## # This is the PICT model specifying all parameters and their values # Exponent: int8, int16, int32 HasComponent: 0,1 StoreHash: 0,1 StoreOrder: 0,1 ############################################################## # PICT submodels go here. # # we are not currently using PICT submodels ############################################################## # This is the set of PICT constraints that rule out some combinations # of parameter values. # mathicgb-master/src/test/monoidPict.seed000077500000000000000000000002131311555162500206450ustar00rootroot00000000000000Exponent HasComponent StoreHash StoreOrder int32 1 1 1 int32 0 1 1 int32 0 0 1 int32 0 0 0 int16 1 1 1 int16 0 1 1 int16 0 0 1 int16 0 0 0 mathicgb-master/src/test/pict.in000077500000000000000000000033631311555162500171760ustar00rootroot00000000000000# The purpose of this file is to generate a set of test configurations # where every pair of parameter values is present at least once. See # the Wikipedia page on all pairs testing: # # http://en.wikipedia.org/wiki/All-pairs_testing # # This file is an input file for the Microsoft testing tool PICT. # The tool is available at # # http://download.microsoft.com/download/f/5/5/f55484df-8494-48fa-8dbd-8c6f76cc014b/pict33.msi # # You will need to run this program on Windows. It is a closed source # utility. There are open sources alternatives but they are not as good. # # To update the test in gb-test.cpp, do # # pict pict.in > pict.out # # Then place the entire contents of pict.out (including newlines) into # the string allPairsTest in gb-test.cpp. ############################################################## # This is the PICT model specifying all parameters and their values # spairQueue: 0,1,2,3 reducerType: 7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26 divLookup: 1, 2, 3, 4 monTable: 1, 2, 3, 4 buchberger: 0, 1 postponeKoszul: 0, 1 useBaseDivisors: 0, 1 autoTailReduce: 0,1 autoTopReduce: 0,1 preferSparseReducers: 0,1 useSingularCriterionEarly: 0, 1 sPairGroupSize: 0, 1, 2, 10, 100 threadCount: 1, 2, 8 ############################################################## # PICT submodels go here. # # we are not currently using PICT submodels ############################################################## # This is the set of PICT constraints that rule out some combinations # of parameter values. # IF [buchberger] = 0 THEN [autoTopReduce] = 0 AND [autoTailReduce] = 0 AND [reducerType] <> 25 AND [reducerType] <> 26; IF [buchberger] = 1 THEN [postponeKoszul] = 0 AND [useBaseDivisors] = 0 AND [usesingularCriterionEarly] = 0; mathicgb-master/src/test/poly-test.cpp000077500000000000000000000475701311555162500203630ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include "mathicgb/Poly.hpp" #include "mathicgb/Basis.hpp" #include "mathicgb/ModuleMonoSet.hpp" #include "mathicgb/io-util.hpp" #include "mathicgb/SigPolyBasis.hpp" #include "mathicgb/SignatureGB.hpp" #include "mathicgb/MathicIO.hpp" #include #include #include #include #include using namespace mgb; std::string ideal1 = "32003 4 1 1 1 1 1 \ 2 \ ab+3d2+2d \ c3+a-b+1 \ "; std::string ideal2 = " \ 32003 4 \ 1 1 1 1 1 \ 7 \ bc2-ad2 \ abc-d3 \ b3-acd \ a2d2-cd3 \ ac3d-ab2d2 \ a2c2d-b2d3 \ c3d3-b2d4 \ "; bool testPolyParse(PolyRing* R, std::string s, bool withComponent) { // parse poly, then see if it matches the orig string std::istringstream i(s); Scanner in(i); auto f = MathicIO<>().readPolyDoNotOrder(*R, withComponent, in); std::ostringstream o; MathicIO<>().writePoly(f, withComponent, o); // std::cout << "orig = " << s << std::endl; // std::cout << "f = " << o.str() << std::endl; return o.str() == s; } bool testPolyParse2(PolyRing* R, std::string s, std::string answer) { // parse poly, then see if it matches the orig string std::istringstream i(s); Scanner scanner(i); auto f = MathicIO<>().readPolyDoNotOrder(*R, false, scanner); std::ostringstream o; MathicIO<>().writePoly(f, false, o); // std::cout << "orig = " << s << std::endl; // std::cout << "f = " << o.str() << std::endl; return o.str() == answer; } TEST(Poly,parse) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); EXPECT_TRUE(testPolyParse(R.get(), "3a<1>+1<0>", true)); EXPECT_TRUE(testPolyParse(R.get(), "3a+1", false)); EXPECT_TRUE(testPolyParse(R.get(), "3a<1>+13af3<0>+14cde<0>", true)); EXPECT_TRUE(testPolyParse(R.get(), "1<1>+13af3<0>+14cde<0>", true)); } bool testMonomialParse(PolyRing* R, std::string s) { Monomial m = stringToMonomial(R, s); std::string str2 = monomialToString(R,m); return s == str2; } TEST(Monomial, parse) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); EXPECT_TRUE(testMonomialParse(R.get(), "ab2d<2>")); EXPECT_TRUE(testMonomialParse(R.get(), "ab2d<0>")); EXPECT_TRUE(testMonomialParse(R.get(), "<13>")); EXPECT_TRUE(testMonomialParse(R.get(), "abcdef<0>")); EXPECT_TRUE(testMonomialParse(R.get(), "a10b3d4<0>")); } TEST(Monomial,compare) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial mone = stringToMonomial(R.get(), "<0>"); Monomial mone2 = stringToMonomial(R.get(), "1"); Monomial m1 = stringToMonomial(R.get(), "ab2<0>"); Monomial m2 = stringToMonomial(R.get(), "a2b<0>"); EXPECT_TRUE(R->monomialEQ(mone, mone2)); // monomial mone = monomialFromString(R, "0 0"); // monomial m1 = monomialFromString(R, "0 2 1 2 0 1"); // monomial m2 = monomialFromString(R, "0 2 1 1 0 2"); bool a = R->monomialLT(m1,m2); EXPECT_TRUE(a); EXPECT_FALSE(R->monomialEQ(m1,m2)); EXPECT_EQ(LT, R->monomialCompare(m1,m2)); a = R->monomialLT(mone,m1); EXPECT_TRUE(a); EXPECT_FALSE(R->monomialEQ(mone,m1)); EXPECT_EQ(GT, R->monomialCompare(m1,mone)); a = R->monomialLT(mone,mone); EXPECT_FALSE(a); EXPECT_TRUE(R->monomialEQ(mone,mone)); EXPECT_EQ(EQ, R->monomialCompare(mone,mone)); Monomial b = stringToMonomial(R.get(), "b<0>"); Monomial c = stringToMonomial(R.get(), "c<0>"); a = R->monomialLT(b,c); EXPECT_FALSE(a); } TEST(Monomial,mult) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial m1 = stringToMonomial(R.get(), "ab2<0>"); Monomial m2 = stringToMonomial(R.get(), "a2b<0>"); Monomial m3ans = stringToMonomial(R.get(), "a3b3<0>"); Monomial m3 = R->allocMonomial(); R->monomialMult(m1,m2,m3); EXPECT_TRUE(R->monomialEQ(m3ans,m3)); R->freeMonomial(m1); R->freeMonomial(m2); R->freeMonomial(m3); R->freeMonomial(m3ans); } TEST(Monomial,multTo) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial m1 = stringToMonomial(R.get(), "ab2<0>"); Monomial m2 = stringToMonomial(R.get(), "a2b<0>"); Monomial m3ans = stringToMonomial(R.get(), "a3b3<0>"); R->monomialMultTo(m1,m2); EXPECT_TRUE(R->monomialEQ(m3ans,m1)); R->freeMonomial(m1); R->freeMonomial(m2); R->freeMonomial(m3ans); } TEST(Monomial, divide) { // test of monomialDivide, monomialIsDivisibleBy, monomialQuotientAndMult std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial m1 = stringToMonomial(R.get(), "ab2<0>"); Monomial m2 = stringToMonomial(R.get(), "a2b<0>"); Monomial m3ans = stringToMonomial(R.get(), "a3b3<0>"); Monomial m3 = R->allocMonomial(); Monomial m1a = R->allocMonomial(); R->monomialMult(m1,m2,m3); EXPECT_TRUE(R->monomialIsDivisibleBy(m3,m2)); EXPECT_FALSE(R->monomialIsDivisibleBy(m2,m3)); R->monomialDivide(m3,m2,m1a); EXPECT_TRUE(R->monomialEQ(m1,m1a)); R->freeMonomial(m1); R->freeMonomial(m2); R->freeMonomial(m3); R->freeMonomial(m3ans); R->freeMonomial(m1a); } TEST(Monomial, monomialQuotientAndMult) { // test of monomialQuotientAndMult std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial m1 = stringToMonomial(R.get(), "ab2f2<0>"); Monomial m2 = stringToMonomial(R.get(), "af<0>"); Monomial m3 = stringToMonomial(R.get(), "<2>"); Monomial n = R->allocMonomial(); Monomial n1 = R->allocMonomial(); Monomial na = R->allocMonomial(); R->monomialQuotientAndMult(m1,m2,m3,n); R->monomialDivide(m1,m2,n1); // m1//m2 R->monomialMult(n1,m3,na); // m1//m2 * m3 should be n EXPECT_TRUE(R->monomialEQ(n, na)); R->freeMonomial(m1); R->freeMonomial(m2); R->freeMonomial(m3); R->freeMonomial(n); R->freeMonomial(n1); R->freeMonomial(na); } void testMonomialOps(const PolyRing* R, std::string s1, std::string s2) { Monomial m1 = stringToMonomial(R, s1); Monomial m2 = stringToMonomial(R, s2); Monomial m3 = stringToMonomial(R, "abcdef<0>"); Monomial m4 = R->allocMonomial(); Monomial lcm = R->allocMonomial(); Monomial m8 = R->allocMonomial(); Monomial m1a = R->allocMonomial(); Monomial m2a = R->allocMonomial(); Monomial m1b = R->allocMonomial(); Monomial m2b = R->allocMonomial(); R->monomialMult(m1,m2,m4); R->monomialLeastCommonMultiple(m1,m2,lcm); // lcm(m1,m2)/m1, lcm(m1,m2)/m2: relatively prime EXPECT_TRUE(R->monomialIsDivisibleBy(lcm, m1)); EXPECT_TRUE(R->monomialIsDivisibleBy(lcm, m2)); R->monomialDivide(lcm, m1, m1a); R->monomialDivide(lcm, m2, m2a); EXPECT_TRUE(R->monomialRelativelyPrime(m1a,m2a)); EXPECT_TRUE(R->monomialIsDivisibleBy(lcm, m1a)); EXPECT_TRUE(R->monomialIsDivisibleBy(lcm, m2a)); R->monomialDivide(lcm, m1a, m1b); R->monomialDivide(lcm, m2a, m2b); EXPECT_TRUE(R->monomialEQ(m1, m1b)); EXPECT_TRUE(R->monomialEQ(m2, m2b)); R->monomialMult(m1a, m2a, m8); size_t supp1 = R->monomialSizeOfSupport(m1a); size_t supp2 = R->monomialSizeOfSupport(m2a); size_t supp = R->monomialSizeOfSupport(m8); EXPECT_EQ(supp1+supp2, supp) << monomialToString(R,m1) << " " << monomialToString(R,m2) << "\n" << monomialToString(R,m1a) << " " << monomialToString(R,m2a) << " " << monomialToString(R,m8); } TEST(Monomial, ops) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); testMonomialOps(R.get(), "ab2f2<0>", "bc2df3<0>"); testMonomialOps(R.get(), "ab2f2<0>", "<0>"); testMonomialOps(R.get(), "<0>", "<0>"); testMonomialOps(R.get(), "a<0>", "a<0>"); testMonomialOps(R.get(), "a<0>", "b<0>"); testMonomialOps(R.get(), "a10b10c10d10e10f10<0>", "b2f5<0>"); } TEST(Monomial, ei) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial m1 = stringToMonomial(R.get(), "<1>"); Monomial m1a = R->allocMonomial(); R->monomialEi(1, m1a); EXPECT_TRUE(R->monomialEQ(m1,m1a)); m1 = stringToMonomial(R.get(), "<0>"); R->monomialEi(0, m1a); EXPECT_TRUE(R->monomialEQ(m1,m1a)); m1 = stringToMonomial(R.get(), "<1>"); R->monomialEi(1, m1a); EXPECT_TRUE(R->monomialEQ(m1,m1a)); m1 = stringToMonomial(R.get(), "<10000>"); R->monomialEi(10000, m1a); EXPECT_TRUE(R->monomialEQ(m1,m1a)); } TEST(Monomial, strict) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial m1 = stringToMonomial(R.get(), "ab2c3d4e"); Monomial m2 = stringToMonomial(R.get(), "ab2c3d4"); Monomial m3 = stringToMonomial(R.get(), "ab2c3d4"); Monomial m4 = stringToMonomial(R.get(), "ab2c3d3e"); EXPECT_TRUE(R->monomialHasStrictlyLargerExponent(m1,m2,m3)); EXPECT_FALSE(R->monomialHasStrictlyLargerExponent(m1,m2,m4)); } TEST(Monomial, divideToNegative) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial m1 = stringToMonomial(R.get(), "ab100<0>"); Monomial m2 = stringToMonomial(R.get(), "ab2c3d4<0>"); Monomial m3 = R->allocMonomial(); Monomial m4 = R->allocMonomial(); Monomial m5 = R->allocMonomial(); Monomial mone = stringToMonomial(R.get(), "<0>"); R->monomialDivideToNegative(m1,m2,m3); R->monomialDivideToNegative(m2,m1,m4); R->monomialMult(m3,m4,m5); EXPECT_TRUE(R->monomialEQ(m5,mone)); m3 = stringToMonomial(R.get(), "ab2c3d4"); m4 = stringToMonomial(R.get(), "ab2c3d3e"); EXPECT_TRUE(R->monomialHasStrictlyLargerExponent(m1,m2,m3)); EXPECT_FALSE(R->monomialHasStrictlyLargerExponent(m2,m2,m4)); } TEST(Monomial, findSignature) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); Monomial v1 = stringToMonomial(R.get(), "abef"); Monomial v2 = stringToMonomial(R.get(), "acdf2"); Monomial u1 = stringToMonomial(R.get(), "f5<13>"); Monomial t1 = R->allocMonomial(); Monomial t1ans = stringToMonomial(R.get(), "cdf6<13>"); R->monomialFindSignature(v1,v2,u1,t1); EXPECT_TRUE(R->monomialEQ(t1,t1ans)); } //#warning "remove this code" #if 0 bool testMonomialOldParse(PolyRing *R, std::string s) { monomial m = monomialParseFromString(R, s); std::string str2 = monomialDisplay(R,m); return s == str2; } TEST(OldMonomial, parse) { PolyRing *R = ringFromString("32003 6 1\n1 1 1 1 1 1"); EXPECT_TRUE(testMonomialOldParse(R, "ab2d<2>")); EXPECT_TRUE(testMonomialOldParse(R, "ab2d<0>")); EXPECT_TRUE(testMonomialOldParse(R, "<13>")); EXPECT_TRUE(testMonomialOldParse(R, "abcdef<0>")); EXPECT_TRUE(testMonomialOldParse(R, "a10b3d4<0>")); } TEST(OldMonomial,compare) { PolyRing *R = ringFromString("32003 6 1\n1 1 1 1 1 1"); monomial mone = monomialFromString(R, "0 0"); monomial m1 = monomialFromString(R, "0 2 1 2 0 1"); monomial m2 = monomialFromString(R, "0 2 1 1 0 2"); bool a = R->monomialLT(m1,m2); EXPECT_TRUE(a); EXPECT_FALSE(R->monomialEQ(m1,m2)); EXPECT_EQ(LT, R->monomialCompare(m1,m2)); a = R->monomialLT(mone,m1); EXPECT_TRUE(a); EXPECT_FALSE(R->monomialEQ(mone,m1)); EXPECT_EQ(GT, R->monomialCompare(m1,mone)); a = R->monomialLT(mone,mone); EXPECT_FALSE(a); EXPECT_TRUE(R->monomialEQ(mone,mone)); EXPECT_EQ(EQ, R->monomialCompare(mone,mone)); monomial b = monomialFromString(R, "0 1 1 1"); monomial c = monomialFromString(R, "0 1 2 1"); a = R->monomialLT(b,c); EXPECT_FALSE(a); } TEST(OldMonomial,mult) { PolyRing *R = ringFromString("32003 6 1\n1 1 1 1 1 1"); monomial m1 = monomialFromString(R, "0 2 1 2 0 1"); // ab2 monomial m2 = monomialFromString(R, "0 2 1 1 0 2"); // a2b // std::cout << "m1 is " << monomialToString(R,m1) << std::endl; //std::cout << "m2 is " << monomialToString(R,m2) << std::endl; monomial m3 = new int[R->maxMonomialSize()]; R->monomialMult(m1,m2,m3); monomial m3ans = monomialFromString(R, "0 2 1 3 0 3"); // a3b3 //std::cout << "answer is " << monomialToString(R,m3) << std::endl; EXPECT_TRUE(R->monomialEQ(m3ans,m3)); } TEST(OldMonomial,multTo) { PolyRing *R = ringFromString("32003 6 1\n1 1 1 1 1 1"); monomial m1 = monomialFromString(R, "0 3 5 2 1 2 0 1"); // ab2 monomial m2 = monomialFromString(R, "0 2 1 1 0 2"); // a2b R->monomialMultTo(m1,m2); monomial m3ans = monomialFromString(R, "0 3 5 2 1 3 0 3"); // a3b3 EXPECT_TRUE(R->monomialEQ(m3ans,m1)); } TEST(OldMonomial, divide) { // test of monomialDivide, monomialIsDivisibleBy, monomialQuotientAndMult PolyRing *R = ringFromString("32003 6 1\n1 1 1 1 1 1"); monomial m1 = monomialFromString(R, "0 3 5 2 1 2 0 1"); // ab2 monomial m2 = monomialFromString(R, "0 2 1 1 0 2"); // a2b monomial m3 = new int[R->maxMonomialSize()]; monomial m1a = new int[R->maxMonomialSize()]; R->monomialMult(m1,m2,m3); EXPECT_TRUE(R->monomialIsDivisibleBy(m3,m2)); EXPECT_FALSE(R->monomialIsDivisibleBy(m2,m3)); R->monomialDivide(m3,m2,m1a); EXPECT_TRUE(R->monomialEQ(m1,m1a)); } TEST(OldMonomial, monomialQuotientAndMult) { // test of monomialQuotientAndMult PolyRing *R = ringFromString("32003 6 1\n1 1 1 1 1 1"); monomial m1 = monomialFromString(R, "0 3 5 2 1 2 0 1"); // ab2f2 monomial m2 = monomialFromString(R, "0 2 5 1 0 1"); // af monomial m3 = monomialFromString(R, "2 0"); // e_2 monomial n = new int[R->maxMonomialSize()]; monomial n1 = new int[R->maxMonomialSize()]; monomial na = new int[R->maxMonomialSize()]; R->monomialQuotientAndMult(m1,m2,m3,n); R->monomialDivide(m1,m2,n1); // m1//m2 R->monomialMult(n1,m3,na); // m1//m2 * m3 should be n // std::cout << "n is " << monomialToString(R,n) << std::endl; // std::cout << "na is " << monomialToString(R,na) << std::endl; EXPECT_TRUE(R->monomialEQ(n, na)); } #endif TEST(Coeff, reciprocal) { std::unique_ptr R(ringFromString("11 6 1\n1 1 1 1 1 1")); coefficient vals[10] = {1,2,3,4,5,6,7,8,9,10}; coefficient ans[10] = {1,6,4,3,9,2,8,7,5,10}; for (int i=0; i<10; i++) { coefficient a = vals[i]; R->coefficientReciprocalTo(a); EXPECT_EQ(ans[i], a); } } TEST(Coeff, reciprocal2) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); for (int i=1; i<32002; i++) { coefficient a1; coefficient a = i; R->coefficientReciprocalTo(a); R->coefficientDivide(1,i,a1); EXPECT_EQ(a,a1); R->coefficientMultTo(a,i); EXPECT_TRUE(a > 0); EXPECT_TRUE(a < 32003); EXPECT_TRUE(a == 1); } } TEST(Coeff, negate) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); for (int i=1; i<32002; i++) { coefficient a1 = i; coefficient a = i; R->coefficientNegateTo(a); EXPECT_TRUE(a > 0); EXPECT_TRUE(a < 32003); R->coefficientAddTo(a1,a); EXPECT_EQ(0,a1); } } TEST(Coeff, addone) { std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); for (int i=0; i<32002; i++) { coefficient a1 = i; coefficient a = i; R->coefficientAddOneTo(a); EXPECT_TRUE(a > 0); EXPECT_TRUE(a < 32003); R->coefficientAddTo(a1,1); EXPECT_EQ(a,a1); } } TEST(MTArray,DivList1) { // We create a table here std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); auto M = ModuleMonoSet::make(R->monoid(), 1, 6, false); std::string mons[2] = { "abc<1>", "a2d<1>" }; for (int i=0; i<2; i++) { monomial m = monomialParseFromString(R.get(), mons[i]); M->insert(m); } // M.display(std::cout); // Now we test membership EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "abc4d<1>"))); EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "a2d2<1>"))); EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "abc<1>"))); EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "a2d<1>"))); EXPECT_FALSE(M->member(monomialParseFromString(R.get(), "a2d<2>"))); EXPECT_FALSE(M->member(monomialParseFromString(R.get(), "ad<1>"))); } TEST(MTArray,KDTree1) { // We create a table here std::unique_ptr R(ringFromString("32003 6 1\n1 1 1 1 1 1")); std::unique_ptr M(ModuleMonoSet::make(R->monoid(), 2, 6, false)); std::string mons[2] = { "abc<1>", "a2d<1>" }; for (int i=0; i<2; i++) { monomial m = monomialParseFromString(R.get(), mons[i]); M->insert(m); } // M.display(std::cout); // Now we test membership EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "abc4d<1>"))); EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "a2d2<1>"))); EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "abc<1>"))); EXPECT_TRUE(M->member(monomialParseFromString(R.get(), "a2d<1>"))); EXPECT_FALSE(M->member(monomialParseFromString(R.get(), "a2d<2>"))); EXPECT_FALSE(M->member(monomialParseFromString(R.get(), "ad<1>"))); } //#warning "remove this code" #if 0 bool test_find_signatures(const PolyRing *R, const_monomial u1, const_monomial u2, const_monomial v1, const_monomial v2) { monomial g = new int[R->maxMonomialSize()]; monomial t1 = new int[R->maxMonomialSize()]; monomial t2 = new int[R->maxMonomialSize()]; monomial x1 = new int[R->maxMonomialSize()]; monomial x2 = new int[R->maxMonomialSize()]; monomial y1 = new int[R->maxMonomialSize()]; monomial y2 = new int[R->maxMonomialSize()]; monomial v1v2 = new int[R->maxMonomialSize()]; monomial x1g = new int[R->maxMonomialSize()]; monomial p = new int[R->maxMonomialSize()]; monomial m = new int[R->maxMonomialSize()]; R->monomialFindSignature(v1,v2,u1,t1); R->monomialFindSignature(v2,v1,u2,t2); R->monomialMult(v1, v2, p); R->monomialLeastCommonMultiple(v1, v2, m); R->monomialDivide(p, m, g); //R->monomialGreatestCommonDivisor(v1, v2, g); // check that v1*t1 == v2*t2 // v1*v2 == g * (v1*t1) R->monomialDivide(t1,u1,y1); R->monomialDivide(t2,u2,y2); // remove mult by signatures R->monomialMult(v1,y1,x1); R->monomialMult(v2,y2,x2); R->monomialMult(v1,v2,v1v2); R->monomialMult(x1,g,x1g); #if 0 std::cout << "v1 is " << monomialToString(R,v1) << std::endl; std::cout << "v2 is " << monomialToString(R,v2) << std::endl; std::cout << "u1 is " << monomialToString(R,u1) << std::endl; std::cout << "u2 is " << monomialToString(R,u2) << std::endl; std::cout << "t1 is " << monomialToString(R,t1) << std::endl; std::cout << "22 is " << monomialToString(R,t2) << std::endl; std::cout << "x1 is " << monomialToString(R,x1) << std::endl; std::cout << "x2 is " << monomialToString(R,x2) << std::endl; std::cout << "y1 is " << monomialToString(R,y1) << std::endl; std::cout << "y2 is " << monomialToString(R,y2) << std::endl; std::cout << "g is " << monomialToString(R,g) << std::endl; std::cout << "v1v2 is " << monomialToString(R,v1v2) << std::endl; std::cout << "x1g is " << monomialToString(R,x1g) << std::endl; #endif if (!R->monomialEQ(x1,x2)) return false; if (!R->monomialEQ(v1v2,x1g)) return false; return true; } TEST(OldMonomial, findSignatures) { PolyRing *R = ringFromString("32003 6 1\n1 1 1 1 1 1"); monomial v1 = monomialFromString(R, "0 3 5 2 1 2 0 1"); // ab2f2 monomial v2 = monomialFromString(R, "0 3 2 3 1 1 0 1"); // abc3 monomial u1 = monomialFromString(R, "2 3 4 1 1 2 0 1"); // monomial u2 = monomialFromString(R, "3 2 1 1 0 2"); // EXPECT_TRUE(test_find_signatures(R,u1,u2,v1,v2)); } #endif TEST(Ideal,readwrite) { // This also tests Poly::iterator std::unique_ptr I = basisParseFromString(ideal1); size_t ngens = I->viewGenerators().size(); EXPECT_TRUE(2 == ngens); // now read and write each generator for (size_t i=0; igetPoly(i); std::ostringstream o; MathicIO<>().writePoly(*f, false, o); std::stringstream ifil(o.str()); Scanner scanner(ifil); EXPECT_TRUE(MathicIO<>().readPoly(f->ring(), false, scanner) == *f); } } TEST(Poly,lead) { // This also tests Poly::iterator, Poly::read, Poly::write std::unique_ptr I = basisParseFromString(ideal1); std::unique_ptr R(I->getPolyRing()); const auto& monoid = R->monoid(); monomial lm = stringToMonomial(R.get(), "ab"); EXPECT_TRUE(monoid.equal(lm, I->getPoly(0)->leadMono())); EXPECT_EQ(1, I->getPoly(0)->leadCoef()); EXPECT_EQ(0, monoid.component(I->getPoly(0)->leadMono())); R->freeMonomial(lm); } mathicgb-master/src/test/testMain.cpp000077500000000000000000000005141311555162500201720ustar00rootroot00000000000000// MathicGB copyright 2012 all rights reserved. MathicGB comes with ABSOLUTELY // NO WARRANTY and is licensed as GPL v2.0 or later - see LICENSE.txt. #include "mathicgb/stdinc.h" #include using namespace mgb; int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }