pax_global_header00006660000000000000000000000064143026612520014513gustar00rootroot0000000000000052 comment=1b0c9da45ab02cef8a93bfa5b7fb66121c65f3bc mwrap-1.1.1/000077500000000000000000000000001430266125200126415ustar00rootroot00000000000000mwrap-1.1.1/COPYING000066400000000000000000000023241430266125200136750ustar00rootroot00000000000000mwrap -- MEX file generation for MATLAB and Octave Copyright (c) 2007-2008 David Bindel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. You may distribute a work that contains part or all of the source code generated by mwrap under the terms of your choice. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mwrap-1.1.1/Makefile000066400000000000000000000003511430266125200143000ustar00rootroot00000000000000include make.inc bin: (cd src; make) test: (cd testing; make) demo: (cd example; make) clean: rm -f mwrap (cd src; make clean) (cd example; make clean) (cd testing; make clean) realclean: clean (cd src; make realclean) mwrap-1.1.1/NEWS000066400000000000000000000050331430266125200133410ustar00rootroot00000000000000Recent updates: Version 1.1 (Jun 7, 2022) Added support for gfortran -fno-underscoring flag Version 1.0 (Aug 4, 2020) Added support for 64-bit Matlab and gcc-4.6 Added support for gcc 7.3+ Added support for Matlab R2018a complex interleaved API Added support for C99 int32_t, int64_t, uint32_t, uint64_t Allow single precision Matlab inputs and outputs Version 0.32 (Nov 5, 2008) Added support for new single-class style MATLAB objects; an example is in the manual, as well as in examples/eventq. Version 0.31 (Jun 19, 2008) Added line to license to clarify that code generated by MWrap may be redistributed under terms of the user's choice. Version 0.30 (Apr 29, 2008): Added more complete support for auto-converted objects, allowing them to be used as inout or output parameters and updating the documentation accordingly. Corrected bug in C call line checking feature (added in 0.28); corrected missing virtual destructor for Quad2d in FEM example. Version 0.29 (Apr 27, 2008): Reworked internal error handling logic. Added typedef mxArray support to allow automatic conversion of mxArrays to temporary objects on input. Version 0.28 (Mar 4, 2008): Added a check against ending a block of C call lines without finishing a statement (e.g. missing a semicolon on an isolated call line). Added support for C++ end-of-line comments inside C call lines. Added partial recovery on syntax errors. Version 0.27 (Feb 19, 2008): Added const arguments. Version 0.26 (Feb 18, 2008): Updated demos. Version 0.25 (Feb 8, 2008): Corrected code to add bounds checks on complex arrays. Added nonzero return codes on error. Version 0.24 (Feb 7, 2008): Added comment lines. Version 0.23 (Feb 6, 2008): Added logging support for profiling / coverage testing. Version 0.22 (Jan 29, 2008): Added @include support. Version 0.21 (Jan 7, 2008): Added support for string literal arguments. Added support for @function redirections. Corrected line number counting in presence of $[ $] code blocks. Version 0.20 (Sep 20, 2007): Added $[ $] delimiters for C code blocks. Version 0.19 (Sep 4, 2007): Added array references. Version 0.18 (August 15, 2007): Added interpretation of empty input array arguments as NULL. Version 0.17 (July 31, 2007): Added scoped names for access to static methods, namespaces. Version 0.16 (July 9, 2007): Added flags to set default complex support to C++ or C99 complex types Version 0.15 (July 5, 2007): Corrected complex support (needs setz macro) Version 0.14 (July 3, 2007): Added complex support Version 0.13 (June 30, 2007): Added FORTRAN bindings mwrap-1.1.1/README000066400000000000000000000040441430266125200135230ustar00rootroot00000000000000MWrap ===== MWrap is an interface generation system in the spirit of SWIG or matwrap. From a set of augmented MATLAB script files, MWrap will generate a MEX gateway to desired C/C++/Fortran function calls and MATLAB function files to access that gateway. It makes wrapping C/C++/Fortran from MATLAB almost pleasant! The details of converting to and from MATLAB's data structures, and of allocating and freeing temporary storage, are hidden from the user. It is also compatible with modern Octave via `mkoctfile --mex`. To compile, edit `make.inc` and then run `make`. The output will be a standalone executable (`mwrap`) in the main directory. It was created by David Bindel, who hosts his old version at https://www.cs.cornell.edu/~bindel/sw/mwrap Example usage ------------- David Bindel's user's guide (`mwrap.pdf`) describes MWrap in detail; you can also look at the example subdirectories and the testing subdirectory to get some idea of how MWrap is used. Alex Barnett also maintains a set of minimally complete tutorial examples of calling C/Fortran libraries (including OpenMP) from MATLAB/Octave, using MWrap, at https://github.com/ahbarnett/mwrapdemo Contributors and version history -------------------------------- MWrap was originally written by David Bindel, c. 2009. It was moved to github in c. 2015 in order to add new features, and is now maintained by Zydrunas Gimbutas, Alex Barnett, Libin Lu, Manas Rachh, and Rafael Laboissière. Version 0.33 (c. 2009) Author: David Bindel Initial revision, clone David's repository (c. 2015) Version 1.0 (c. 2020) Contributors: Zydrunas Gimbutas, Alex Barnett, Libin Lu. Add support for 64-bit Matlab and gcc-4.6 Add support for gcc 7.3+ Add support for Matlab R2018a complex interleaved API Add support for C99 int32_t, int64_t, uint32_t, uint64_t Allow single precision Matlab inputs and outputs Version 1.1 (2022) Contributors: Manas Rachh, Zydrunas Gimbutas. Add support for gfortran -fno-underscoring flag Also see https://github.com/zgimbutas/mwrap/tags mwrap-1.1.1/doc/000077500000000000000000000000001430266125200134065ustar00rootroot00000000000000mwrap-1.1.1/doc/mwrap.1000066400000000000000000000047511430266125200146250ustar00rootroot00000000000000.TH MWRAP 1 2012 "mwrap" "MWRAP manpage" .SH NAME mwrap - Octave/MATLAB mex generator .SH SYNOPSIS .SY mwrap .OP \-mex \fIoutputmex\fP .OP \-m \fIoutput.m\fP .OP \-c \fIoutputmex.c\fP .OP \-mb .OP \-list .OP \-catch .OP \-i8 .OP \-c99complex .OP \-cppcomplex \fIinfile1\fP \fIinfile2\fP ... .br .SH DESCRIPTION .LP \fBmwrap\fP is an interface generation system in the spirit of SWIG or matwrap. From a set of augmented Octave/MATLAB script files, \fBmwrap\fP will generate a MEX gateway to desired C/C++ function calls and \.m function files to access that gateway. The details of converting to and from Octave's or MATLAB's data structures, and of allocating and freeing temporary storage, are hidden from the user. .SH OPTIONS .TP .B \-mex specifies the name of the MEX function that the generated functions will call. This name will generally be the same as the prefix for the C/C++ output file name. . .TP .B \-m specifies the name of the Octave/MATLAB script to be generated. . .TP .B \-c specifies the name of the C MEX file to be generated. The MEX file may contain stubs corresponding to several different generated files. . .TP .B \-mb redirect Octave/MATLAB function output to files named in the input. In this mode, the processor will change Octave/MATLAB function output files whenever it encounters a line beginning with @. If @ occurs alone on a line, the output will be turned off; if the line begins with @function, the line will be treated as the first line of a function, and the m-file name will be deduced from the function name; and otherwise, the characters after @ (up to the next set of white space) will be treated as a filename, and \fBmwrap\fP will try to write to that file. . .TP .B \-list print to the standard output the names of all files that would be generated from redirect output by the \-mb flag. . .TP .B \-catch surround library calls in try/catch blocks in order to intercept C++ exceptions. . .TP .B \-i8 convert \fBint\fP, \fBlong\fP, \fBuint\fP, \fBulong\fP types to \fBint64_t\fP, \fBuint64_t\fP. This provides a convenient way to interface with \fB-fdefault-integer-8\fP and \fB-i8\fP flags used by Fortran compilers. . .TP .B \-c99complex use the C99 complex floating point types as the default \fBdcomplex\fP and \fBfcomplex\fP types. . .TP .B \-cppcomplex use the C++ complex floating point types as the default \fBdcomplex\fP and \fBfcomplex\fP types. .SH AUTHORS .LP \fBmwrap\fP is written by David Bindel and Zydrunas Gimbutas. This manual page was written by Nicolas Bourdaud. mwrap-1.1.1/doc/mwrap.tex000066400000000000000000000761321430266125200152670ustar00rootroot00000000000000\documentclass[12pt]{article} \usepackage{amsmath} \usepackage{fancyheadings} \setlength{\oddsidemargin}{0.0in} \setlength{\textwidth}{6.5in} \setlength{\topmargin}{-0.5in} \setlength{\textheight}{9.0in} \bibliographystyle{unsrt} \renewcommand{\baselinestretch}{1.0} \newcommand{\mwrap}{\textsc{MWrap}} \newcommand{\gOR}{ $|$ } \title{\mwrap\ User Guide\\ Version 1.1} \author{D. Bindel} \pagestyle{fancy} %%\headrulewidth 1.5pt %%\footrulewidth 1.5pt \chead{\mwrap} \lhead{} \rhead{} \cfoot{\thepage} \begin{document} \maketitle \section{Introduction} \mwrap\ is an interface generation system in the spirit of SWIG or matwrap. From a set of augmented MATLAB script files, \mwrap\ will generate a MEX gateway to desired C/C++ function calls and MATLAB function files to access that gateway. The details of converting to and from MATLAB's data structures, and of allocating and freeing temporary storage, are hidden from the user. \mwrap\ files look like MATLAB scripts with specially formatted extra lines that describe calls to C/C++. For example, the following code is converted into a call to the C {\tt strncat} function: \begin{verbatim} $ #include function foobar; s1 = 'foo'; s2 = 'bar'; # strncat(inout cstring[128] s1, cstring s2, int 127); fprintf('Should be foobar: %s\n', s1); \end{verbatim} There are two structured comments in this file. The line beginning with \verb|$| tells \mwrap\ that this line is C/C++ support code, and the line beginning with \verb|#| describes a call to the C {\tt strncat} function. The call description includes information about the C type to be used for the input arguments, and also describes which parameters are used for input and for output. From this input file, \mwrap\ produces two output files: a C file which will be compiled with the MATLAB {\tt mex} script, and a MATLAB script which calls that MEX file. If the above file is {\tt foobar.mw}, for example, we would generate an interface file {\tt foobar.m} and a MEX script {\tt fbmex.mex} with the lines \begin{verbatim} mwrap -mex fbmex -m foobar.m foobar.mw mwrap -mex fbmex -c fbmex.c foobar.mw mex fbmex.c \end{verbatim} At this point, we can run the {\tt foobar} script from the MATLAB prompt: \begin{verbatim} >> foobar Should be foobar: foobar \end{verbatim} Versions of GNU Octave released after mid-2006 support much of MATLAB's MEX interface. Simple {\mwrap}-generated code should work with GNU Octave. To compile for GNU Octave, use \texttt{mkoctfile --mex} instead of invoking \texttt{mex}. GNU Octave does not implement MATLAB's object model, so code that uses MATLAB's object-oriented facilities will not function with GNU Octave. \section{\mwrap\ command line} The {\tt mwrap} command line has the following form: \begin{verbatim} mwrap [-mex outputmex] [-m output.m] [-c outputmex.c] [-mb] [-list] [-catch] [-i8] [-c99complex] [-cppcomplex] infile1 infile2 ... \end{verbatim} where \begin{itemize} \item {\tt -mex} specifies the name of the MEX function that the generated MATLAB functions will call. This name will generally be the same as the prefix for the C/C++ output file name. \item {\tt -m} specifies the name of the MATLAB script to be generated. \item {\tt -c} specifies the name of the C MEX file to be generated. The MEX file may contain stubs corresponding to several different generated MATLAB files. \item {\tt -mb} tells \mwrap\ to redirect MATLAB function output to files named in the input. In this mode, the processor will change MATLAB function output files whenever it encounters a line beginning with \verb|@|. If \verb|@| occurs alone on a line, MATLAB output will be turned off; if the line begins with \verb|@function|, the line will be treated as the first line of a function, and the m-file name will be deduced from the function name; and otherwise, the characters after \verb|@| (up to the next set of white space) will be treated as a filename, and \mwrap\ will try to write to that file. \item {\tt -list} tells \mwrap\ to print to the standard output the names of all files that would be generated from redirect output by the {\tt -mb} flag. \item {\tt -catch} tells \mwrap\ to surround library calls in try/catch blocks in order to intercept C++ exceptions. \item {\tt -i8} tells \mwrap\ to convert {\tt int}, {\tt long}, {\tt uint}, {\tt ulong} types to {\tt int64\_t}, {\tt uint64\_t}. This provides a convenient way to interface with {\tt -fdefault-integer-8} and {\tt -i8} flags used by Fortran compilers. \item {\tt -c99complex} tells \mwrap\ to use the C99 complex floating point types as the default {\tt dcomplex} and {\tt fcomplex} types. \item {\tt -cppcomplex} tells \mwrap\ to use the C++ complex floating point types as the default {\tt dcomplex} and {\tt fcomplex} types. \end{itemize} \section{Interface syntax} \subsection{Input line types} \mwrap\ recognizes six types of lines, based on the first non-space characters at the start of the line: \begin{itemize} \item C support lines begin with \verb|$|. These lines are copied into the C code that makes up the MEX file. Typically, such support lines are used to include any necessary header files; they can also be used to embed short functions. \item Blocks of C support can be opened by the line \verb|$[| and closed by the line \verb|$]|. Like lines beginning with \verb|$|, lines that fall between the opening and closing markers are copied into the C code that makes up the MEX file. \item C call lines begin with \verb|#|. These lines are parsed in order to generate an interface function as part of the MEX file and a MATLAB call line to invoke that interface function. C call lines can refer to variables declared in the local MATLAB environment. \item Input redirection lines (include lines) begin with \verb|@include|. The input file name should not be quoted in any way. \item Output redirection lines begin with \verb|@|. % Output redirection is used to specify several generated MATLAB scripts with a single input file. \item Comment lines begin with \verb|//|. Comment lines are not included in any output file. \item All other lines are treated as ordinary MATLAB code, and are passed through to a MATLAB output file without further processing. \end{itemize} \subsection{C call syntax} The complete syntax for \mwrap\ call statements is given in Figure~\ref{mwrap-syntax-fig}. Each statement makes a function or method call, and optionally assigns the output to a variable. For each argument or return variable, we specify the type and also say whether the variable is being used for input, for output, or for both. Variables are given by names which should be valid identifiers in the local MATLAB environment where the call is to be made. Input arguments can also be given numeric values, though it is still necessary to provide type information. There are three types of call specifications. Ordinary functions not attached to a class can be called by name: \begin{verbatim} # do_something(); \end{verbatim} To create a new C++ object instance, we use the {\tt new} command \begin{verbatim} # Thermometer* therm = new Thermometer(double temperature0); \end{verbatim} And once we have a handle to an object, we can invoke methods on it \begin{verbatim} # double temperature = therm->Thermometer.get_temperature(); \end{verbatim} Object deletion is handled just like an ordinary function call \begin{verbatim} # delete(Thermometer* therm); \end{verbatim} Intrinsic operators like {\tt sizeof} can also be invoked in this manner. The type specifications are \emph{only} used to determine how \mwrap\ should handle passing data between MATLAB and a C/C++ statement; the types specified in the call sequence should be compatible with a corresponding C/C++ definition, but they need not be identical to the types in a specific function or method declaration. An \mwrap\ type specification consists of three parts. The first (optional) part says whether the given variable will be used for input ({\tt input}), for output ({\tt output}), or for both. The second part gives the basic type name for the variable; this may be an intrinsic type like {\tt int} or {\tt double}, a string, an object type, or a MATLAB intrinsic (see Section~\ref{type-section}). Finally, there may be modifiers to specify that this is a pointer, a reference, or an array. Array and string arguments may also have explicitly provided size information. In the example from the introduction, for example the argument declaration \begin{verbatim} inout cstring[128] s1 \end{verbatim} tells \mwrap\ that {\tt s1} is a C string which is used for input and output, and that the buffer used should be at least 128 characters long. Identifiers in \mwrap\ may include C++ scope specifications to indicate that a function or method belongs to some namespace or that it is a static member of a class. That is, it is valid to write something like \begin{verbatim} std::ostream* os = foo->get_ostream(); \end{verbatim} Scoped names may be used for types or for method names, but it is an unchecked error to use a scoped name for a parameter or return variable. \begin{figure} \begin{center} \begin{tabular}{l@{ := }l} statement & returnvar {\tt = } func {\tt (} args {\tt );} \\ & func {\tt (} args {\tt );} \\ & {\tt typedef numeric} {\it type-id} {\tt ;} \\ & {\tt typedef dcomplex} {\it type-id} {\tt ;} \\ & {\tt typedef fcomplex} {\it type-id} {\tt ;} \\ & {\tt class} {\it child-id} {\tt :} {\it parent-id} {\tt ,} {\it parent-id} {\tt ,} $\ldots$ \vspace{5mm} \\ func & {\it function-id} \\ & {\tt FORTRAN} {\it function-id} \\ & {\it this-id} {\tt .} {\it class-id} {\tt ->} {\it method-id}\\ & {\tt new} {\it class-id} \vspace{5mm} \\ args & arg {\tt ,} arg {\tt ,} $\ldots$ \gOR\ $\epsilon$ \\ arg & iospec type {\it var-id} \\ & ispec type {\it value} \\ returnvar & type {\it var-id} \vspace{5mm} \\ iospec & {\tt input} \gOR\ {\tt output} \gOR\ {\tt inout} \gOR\ $\epsilon$ \\ ispec & {\tt input} \gOR\ $\epsilon$ \\ type & {\it type-id} \gOR {\it type-id} {\tt *} \gOR\ {\it type-id} {\tt \&} \gOR\ {\it type-id} {\tt [} dims {\tt]} \gOR\ {\it type-id} {\tt [} dims {\tt] \&} \\ dims & dim {\tt ,} dim {\tt ,} $\ldots$ \gOR\ $\epsilon$ \\ dim & {\it var-id} \gOR\ {\it number} \end{tabular} \caption{\mwrap\ call syntax} \label{mwrap-syntax-fig} \end{center} \end{figure} \section{Variable types} \label{type-section} \mwrap\ recognizes several different general types of variables as well as constant expressions: \subsection{Numeric types} {\it Scalars} are intrinsic numeric types in C/C++: {\tt double}, {\tt float}, {\tt long}, {\tt int}, {\tt char}, {\tt ulong}, {\tt uint}, {\tt uchar}, {\tt bool}, {\tt int32\_t}, {\tt uint32\_t}, {\tt int64\_t}, {\tt uint64\_t}, {\tt ptrdiff\_t} and {\tt size\_t}. These are the numeric types that \mwrap\ knows about by default, but if necessary, new numeric types can be declared using {\tt typedef} commands. For example, if we wanted to use {\tt float64\_t} as a numeric type, we would need the line \begin{verbatim} # typedef numeric float64_t; \end{verbatim} Ordinary scalars cannot be used as output arguments. {\it Scalar pointers} are pointers to the recognized numeric intrinsics. They are assumed to refer to {\em one} variable; that is, a {\tt double*} in \mwrap\ is a pointer to one double in memory, which is different from a double array ({\tt double[]}). {\it Scalar references} are references to the recognized numeric intrinsics. {\it Arrays} store arrays of recognized numeric intrinsics. They may have explicitly specified dimensions (in the case of pure return arrays and pure output arguments, they \emph{must} have explicitly specified dimensions), but the dimensions can also be automatically determined from the input data. If only one dimension is provided, return and output arrays are allocated as column vectors. If a function is declared to return an array or a scalar pointer and the C return value is NULL, \mwrap\ will pass an empty array back to MATLAB. If an empty array is passed to a function as an input array argument, \mwrap\ will interpret that argument as NULL. {\it Array references} are references to numeric arrays, such as in a function whose C++ prototype looks like \begin{verbatim} void output_array(const double*& data); \end{verbatim} Array references may only be used as output arguments, and the array must have explicitly specified dimensions. If the value of the data pointer returned from the C++ function is NULL, \mwrap\ will pass an empty array back to MATLAB. {\it Complex} scalars pose a special challenge. C++ and C99 provide distinct complex types, and some C89 libraries define complex numbers via structures. If the {\tt -cppcomplex} or {\tt -c99complex} flags are specified, {\tt mwrap} will automatically define complex double and single precision types {\tt dcomplex} and {\tt fcomplex} which are bound to the C++ or C99 double-precision and single-precision complex types. More generally, we allow complex numbers which are conceptually pairs of floats or doubles to be defined using {\tt typedef fcomplex} and {\tt typedef dcomplex} commands. For example, in C++, we might use the following commands to set up a double complex type {\tt cmplx} (which is equivalent to the {\tt dcomplex} type when the {\tt -cppcomplex} flag is used): \begin{verbatim} $ #include $ typedef std::complex cmplx; // Define a complex type $ #define real_cmplx(z) (z).real() // Accessors for real, imag $ #define imag_cmplx(z) (z).imag() // (req'd for complex types) $ #define setz_cmplx(z,r,i) *z = dcomplex(r,i) # typedef dcomplex cmplx; \end{verbatim} The macro definitions {\tt real\_cmplx}, {\tt imag\_cmplx}, and {\tt setz\_cmplz} are used by \mwrap\ to read or write the real and imaginary parts of a number of type {\tt cmplx}. Similar macro definitions must be provided for any other complex type to be used. Other than any setup required to define what will be used as a complex type, complex scalars can be used in all the same ways that real and integer scalars are used. \subsection{Strings} {\it Strings} are C-style null-terminated character strings. They are specified by the \mwrap\ type {\tt cstring}. A {\tt cstring} type is not equivalent to a {\tt char[]} type, since the latter is treated as an array of numbers (represented by a double vector in MATLAB) in which zero is given no particular significance. The dimensions can be of a {\tt cstring} can explicitly specified or they can be implicit. When a C string is used for output, the size of the corresponding character buffer \emph{must} be given; and when a C string is used for input, the size of the corresponding character buffer should not be given. If a function is declared to return a C string and the return value is NULL, \mwrap\ will pass back the scalar 0. \subsection{Objects} {\it Objects} are variables with any base type other than one of the recognized intrinsics (or the {\tt mxArray} pass-through -- see below). This can lead to somewhat startling results when, for example, \mwrap\ decides a {\tt size\_t} is a dynamic object type (this will only give surprises if one tries to pass in a numeric value). If a function or method returns an object, \mwrap\ will make a copy of the return object on the heap and pass back that copy. {\it Object references} are treated the same as objects, except that when a function returns an object reference, \mwrap\ will return the address associated with that reference, rather than making a new copy of the object. {\it Object pointers} may either point to a valid object of the appropriate type or to NULL (represented by zero). This is different from the treatment of objects and object references. When a NULL value is specified for a {\tt this} argument, an object argument, or an object reference argument, \mwrap\ will generate a MATLAB error message. If the wrapped code uses an object hierarchy, you can use \mwrap\ class declarations so that valid casts to parent types will be performed automatically. For example, the declaration \begin{verbatim} # class Child : Parent1, Parent2; \end{verbatim} tells \mwrap\ that an object of type {\tt Child} may be passed in where an object of type {\tt Parent1} is required. The generated code works correctly with C++ multiple inheritance. Objects cannot be declared as output or inout parameters, but that just means that the identity of an object parameter does not change during a call. There's nothing wrong with changing the internal state of the object. By default, \mwrap\ stores non-NULL object references in strings. However, for MATLAB 2008a and onward, \mwrap\ will also interpret as objects any classes with a readable property {\tt mwptr}. This can be used, for example, to implement class wrappers using the new {\tt classdef} keyword. In order to use this feature, the macro {\tt R2008OO} must be defined by adding the argument {\tt -DR2008OO} to the {\tt mex} compile line. \subsection{{\tt mxArray}} The {\it mxArray} type in \mwrap\ refers to MATLAB's basic object type (also called {\tt mxArray}). {\tt mxArray} arguments can be used as input or output arguments (but not as inout arguments), or as return values. On input, {\tt mxArray} is mapped to C type {\tt const mxArray*}; on output, it is mapped to {\tt mxArray**}; and on return, it is mapped to {\tt mxArray*}. For example, the line \begin{verbatim} # mxArray do_something(mxArray in_arg, output mxArray out_arg); \end{verbatim} is compatible with a function defined as \begin{verbatim} mxArray* do_something(const mxArray* in_arg, mxArray** out_arg); \end{verbatim} Note that the header file {\tt mex.h} must be included for this function declaration to make any sense. The primary purpose for the mxArray pass through is to allow specialized routines to read the internal storage of MATLAB sparse matrices (and possibly other structures) for a few routines without giving up the convenience of the \mwrap\ framework elsewhere. \subsection{Auto-converted objects} If there is a natural mapping from some MATLAB data structure to a C/C++ object type, you can use a typedef to tell \mwrap\ to perform automatic conversion. For example, if we wanted {\tt Foo} to be automatically converted from some MATLAB data structure on input, then we would add the line \begin{verbatim} # typedef mxArray Foo; \end{verbatim} With this declaration, {\tt Foo} objects are automatically converted from {\tt mxArray} to the corresponding C++ type on input, and back to {\tt mxArray} objects on output. It is assumed that \mwrap\ {\em owns the argument objects} and {\em does not own the return objects}. This feature should not be used when the C++ side keeps a pointer or reference to a passed object, or when the caller is responsible for deleting a dynamically allocated return object. Auto-converted objects rely on the following user-defined functions: \begin{verbatim} Foo* mxWrapGet_Foo(const mxArray* a, const char** e); mxArray* mxWrapSet_Foo(Foo* o); Foo* mxWrapAlloc_Foo(); void mxWrapFree_Foo(Foo* o); \end{verbatim} Not all functions are needed for all uses of an auto-converted type. The functions play the following roles: \begin{enumerate} \item The \verb|mxWrapGet_Foo| function is used to convert an input argument to the corresponding C++ representation. If an error occurs during conversion, the second argument should be pointed toward an error message string. It is assumed that this conversion function will catch any thrown exceptions. \item The \verb|mxWrapSet_Foo| function is used to convert an output argument or return value to the corresponding C++ representation. \item The \verb|mxWrapAlloc_Foo| function is used to allocate a new temporary for use as an output argument. \item The \verb|mxWrapFree_Foo| function is used to deallocate a temporary created by \verb|mxWrapGet_Foo| or \verb|mxWrapAlloc_Foo|. \end{enumerate} The point of auto-converted objects is to simplify wrapper design for codes that make heavy use of things like C++ vector classes (for example). The system does {\em not} provide the same flexibility as the {\tt mxArray} object, nor is it as flexible as a sequence of \mwrap\ calls to explicitly create and manage temporaries and their conversion to and from MATLAB objects. At present, the behavior when you try to involve an auto-converted object in an inheritance relation is undefined. Don't try it at home. \subsection{Constants} The {\it const} type in \mwrap\ refers to a C/C++ symbolic constant or global variable. The name of the variable is output directly into the compiled code. For example, to print a string to {\tt stderr}, we can write \begin{verbatim} # fprintf(const stderr, cstring s); \end{verbatim} \subsection{Constants} The {\it const} type in \mwrap\ refers to a C/C++ symbolic constant or global variable. The name of the variable is output directly into the compiled code. For example, to print a string to {\tt stderr}, we can write \begin{verbatim} # fprintf(const stderr, cstring s); \end{verbatim} \subsection{{\tt mxSINGLE\_CLASS} and {\tt mxDOUBLE\_CLASS}} By default, {\tt mwrap 0.33} expected all input and output numeric MATLAB variables to be of {\tt mxDOUBLE\_CLASS}. The newest version of {\tt mwrap (0.33.12+)} allows {\tt mxSINGLE\_CLASS} for {\tt float} and {\tt fcomplex} types. An error {\tt 'Invalid array argument, mxSINGLE/DOUBLE\_CLASS expected'} will be issued if a mismatched Matlab variable is detected during runtime. The user is expected to perform the required type conversions manually using {\tt single} or {\tt double} MATLAB commands. \section{Example} An event queue stores pairs $(i, t)$ pairs, $i$ is an identifier for some event and $t$ is a time associated with the event. Events can be added to the queue in whatever order, but they are removed in increasing order by time. In this example, we bind to a C++ event queue implementation based on the C++ standard template library priority queue. The example code is in {\tt example/eventq/eventq\_class.mw} and {\tt example/eventq/eventq\_handle.mw}; an alternate version of the code in {\tt example/eventq/eventq\_plain.mw} illustrates a different way of organizing the same interface. The {\tt example/eventq2} subdirectory provides yet another implementation, this one capable of storing arbitrary MATLAB arrays rather than just integers. \subsection{Event queue using old MATLAB OO} We begin by defining an event as a pair (double, int), and an event queue as an STL priority queue of such pairs, sorted in descending order: \begin{verbatim} $ #include $ $ typedef std::pair Event; $ typedef std::priority_queue< Event, $ std::vector, $ std::greater > EventQueue; \end{verbatim} Now we specify the code to wrap the individual methods. For this example, we will take advantage of the object oriented features in MATLAB, and map the methods of the C++ event queue class onto methods of a MATLAB wrapper class called {\tt eventq}. We begin with bindings for the constructor and destructor. We will compile the MATLAB functions for the interface using the {\tt -mb} flag, so that we can specify these functions (and all the others) in the same file: \begin{verbatim} @ @eventq/eventq.m ------------------------------------- function [qobj] = eventq(); qobj = []; # EventQueue* q = new EventQueue(); qobj.q = q; qobj = class(qobj, 'eventq'); @ @eventq/destroy.m ------------------------------------- function destroy(qobj); q = qobj.q; # delete(EventQueue* q); \end{verbatim} The {\tt empty} method returns a {\tt bool}, but \mwrap\ does not know about {\tt bool} variables. A {\tt bool} result can be saved as an integer, though, so we will simply do that: \begin{verbatim} @ @eventq/empty.m ------------------------------------- function [e] = empty(qobj) q = qobj.q; # int e = q->EventQueue.empty(); \end{verbatim} Because {\tt pop\_event} needs to return two values (the event identifier and the time), we use reference arguments to pass out the information. \begin{verbatim} @ @eventq/pop_event.m ------------------------------------- function [id, t] = pop_event(qobj) $ void pop_event(EventQueue* q, int& id, double& t) { $ t = q->top().first; $ id = q->top().second; $ q->pop(); $ } $ q = qobj.q; # pop_event(EventQueue* q, output int& id, output double& t); \end{verbatim} In MATLAB, it may make sense to simultaneously push several events. However, our event queue class only provides basic interfaces to push one event at a time. We could write a MATLAB loop to add events to the queue one at a time, but for illustrating how to use \mwrap, it is better to write the loop in C: \begin{verbatim} @ @eventq/push_event.m ------------------------------------- function push_event(qobj, id, t) $ void push_events(EventQueue* q, int* id, double* t, int m) $ { $ for (int i = 0; i < m; ++i) $ q->push(Event(t[i], id[i])); $ } $ q = qobj.q; m = length(id); # push_events(EventQueue* q, int[m] id, double[m] t, int m); \end{verbatim} \subsection{Event queue using new MATLAB OO} Starting with MATLAB 7.6 (release 2008A), MATLAB supports a new single-file OO programming style. Particularly convenient for writing wrappers is the {\em handle} class system, which allows the user to define destructors that are called automatically when an instance is destroyed by the system (because all references to the instance have gone out of scope). As a programming convenience, \mwrap\ automatically interprets a class with the property {\tt mwptr} as a container for an \mwrap\ object\footnote{This functionality is only enabled when {\tt -DR2008OO} is specified as an argument on the MEX command line. This restriction is in place so that the files generated by \mwrap\ can remain compatible with Octave and with older versions of MATLAB.}. For example, the following file provides an alternate implementation of the event queue class described in the previous section. \begin{verbatim} $ #include $ $ typedef std::pair Event; $ typedef std::priority_queue< Event, $ std::vector, $ std::greater > EventQueue; @ eventqh.m ---------------------------------------------- classdef eventqh < handle properties mwptr end methods function [qobj] = eventqh(obj) # EventQueue* q = new EventQueue(); qobj.mwptr = q; end function delete(q) #delete(EventQueue* q); end function e = empty(q) # int e = q->EventQueue.empty(); end function [id, t] = pop(q) $ void pop_event(EventQueue* q, int& id, double& t) { $ t = q->top().first; $ id = q->top().second; $ q->pop(); $ } # pop_event(EventQueue* q, output int& id, output double& t); end function push(q, id, t) $ void push_events(EventQueue* q, int* id, double* t, int m) $ { $ for (int i = 0; i < m; ++i) $ q->push(Event(t[i], id[i])); $ } m = length(id); # push_events(EventQueue* q, int[m] id, double[m] t, int m); end end end \end{verbatim} This implementation of the event queue class allows for automatic cleanup: \begin{verbatim} q = eventqh(); % Construct a new queue clear q; % The C++ object gets correctly deleted here \end{verbatim} {\bf Warning}: When using MATLAB handle classes for automatic cleanup, be sure to avoid situations where multiple MATLAB handle objects have been given responsible for deleting a single C/C++ object. If you need to have more than one MATLAB handle for a single C/C++ object, I recommend using a reference counted pointer class as an intermediate\footnote{ For more information on reference counted pointer classes, I recommend reading {\em More Effective C++} by Scott Meyers. }. \section{FORTRAN bindings} It is possible to use \mwrap\ to bind FORTRAN functions (though the generated MEX file is still a C/C++ file). FORTRAN bindings can be specified using the {\tt FORTRAN} keyword immediately before a function name; for example: \begin{verbatim} # double sum = FORTRAN dasum(int n, double[n] x, int 1); \end{verbatim} FORTRAN parameters are treated differently from C parameters in the following ways: \begin{enumerate} \item \mwrap\ does not allow objects to be passed into FORTRAN functions. \item Scalar and reference arguments are automatically converted to pointer arguments from the C side to match FORTRAN call-by-reference semantics. \item A warning is generated when passing C strings into FORTRAN. The generated code will work with compilers that produce f2c-compatible code (including g77/g95), but it will not work with all FORTRAN compilers. \item Only simple numeric values can be returned from FORTRAN. A warning is generated when returning complex values, as different FORTRAN compilers follow different protocols when returning complex numbers. The generated code for complex return types will work with some f2c-compatible compilers, but by no means all. \end{enumerate} Internally, \mwrap\ defines macros for different FORTRAN name-mangling conventions, and it declares appropriate prototypes (and protects them from C++ compiler name mangling). By default, \mwrap\ assumes that the f2c name mangling convention is being used (this convention is followed by Sun FORTRAN, g77, and g95); however, the following flags can be passed to the {\tt mex} script to change this behavior: \begin{itemize} \item {\tt -DMWF77\_CAPS} -- Assume the FORTRAN compiler uses all-caps names and no extra underscores. Used by Compaq FORTRAN, and Intel fortran compiler on windows (I think). \item {\tt -DMWF77\_UNDERSCORE1} -- Append a single underscore to an all-lower-case name. Used by the GNU FORTRAN compiler and the Intel fortran compiler on UNIX systems (I think). \item {\tt -DMWF77\_UNDERSCORE0} -- Append no underscore to an all-lower-case name. Used by the GNU fortran with the -fno-underscoring flag \end{itemize} It is possible to use the {\tt typedef numeric} construct to introduce new types corresponding to FORTRAN data types. For example, if the header file {\tt f2c.h} is available (and the types defined therein are appropriate for the compiler) we might have \begin{verbatim} % Use the f2c integer type... $ #include "f2c.h" # typedef numeric integer; # double sum = FORTRAN dasum(integer n, double[n] x, integer 1); \end{verbatim} No attempt is made to automatically produce these type maps, though. \section{Logging} For profiling and coverage testing, it is sometimes useful to track the number of calls that are made through \mwrap. If {\tt mymex} is the name of the generated MEX file, then we can access profile information as follows: \begin{verbatim} % Enable profiler mymex('*profile on*'); % Run some tests here... % Print to screen and to a log file mymex('*profile report*'); mymex('*profile log*', 'log.txt'); % Disable profiler mymex('*profile off*'); \end{verbatim} The MEX file will be locked in memory as long as profiling is active. \end{document} mwrap-1.1.1/example/000077500000000000000000000000001430266125200142745ustar00rootroot00000000000000mwrap-1.1.1/example/Makefile000066400000000000000000000003411430266125200157320ustar00rootroot00000000000000all: (cd foobar; make) (cd eventq; make) (cd eventq2; make) (cd zlib; make) (cd fem; make) clean: (cd foobar; make clean) (cd eventq; make clean) (cd eventq2; make clean) (cd zlib; make clean) (cd fem; make clean) mwrap-1.1.1/example/eventq/000077500000000000000000000000001430266125200155765ustar00rootroot00000000000000mwrap-1.1.1/example/eventq/Makefile000066400000000000000000000007061430266125200172410ustar00rootroot00000000000000include ../../make.inc MW=../../mwrap all: pmex cmex hmex pmex: $(MW) -mex eventqpmex -c eventqpmex.cc -mb eventq_plain.mw $(MEX) eventqpmex.cc hmex: $(MW) -mex eventqhmex -c eventqhmex.cc -mb eventq_handle.mw $(MEX) eventqhmex.cc cmex: mkdir -p \@eventq $(MW) -mex eventqcmex -c eventqcmex.cc -mb eventq_class.mw $(MEX) eventqcmex.cc clean: rm -rf \@eventq/ rm -f EventQ_*.m eventqh.m rm -f eventqcmex.* eventqpmex.* eventqhmex.* *.o *~ mwrap-1.1.1/example/eventq/README000066400000000000000000000013621430266125200164600ustar00rootroot00000000000000Example of bindings to encapsulate a C++ class. In this case, we bind the methods for an event queue of (id, time) pairs based on the STL priority queue class. This directory contains two different versions of the example. The "plain" version uses the prefix "EventQ_" to disambiguate references to class methods. For example, "EventQ_empty" would refer to the "empty" method of the event queue class. The "class" version uses the object-oriented features in MATLAB to wrap the C++ class in a MATLAB class, so that the "empty" method in C++ can be mapped to the "empty" method in MATLAB without fear of conflict with any other methods of the same name. Because Octave does not support MATLAB-style OO, this latter version does not work with Octave. mwrap-1.1.1/example/eventq/eventq_class.mw000066400000000000000000000027561430266125200206440ustar00rootroot00000000000000% eventq_class.mw % Simple event queue for use in MATLAB event-driven simulations. % Uses the MATLAB OO system for encapsulating the event queue. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $ #include $ $ typedef std::pair Event; $ typedef std::priority_queue< Event, $ std::vector, $ std::greater > EventQueue; @ @eventq/eventq.m ------------------------------------- function [qobj] = eventq(); qobj = []; # EventQueue* q = new EventQueue(); qobj.q = q; qobj = class(qobj, 'eventq'); @ @eventq/destroy.m ------------------------------------- function destroy(qobj); q = qobj.q; # delete(EventQueue* q); @ @eventq/empty.m ------------------------------------- function [e] = empty(qobj) q = qobj.q; # int e = q->EventQueue.empty(); @ @eventq/pop.m ------------------------------------- function [id, t] = pop(qobj) $ void pop_event(EventQueue* q, int& id, double& t) { $ t = q->top().first; $ id = q->top().second; $ q->pop(); $ } $ q = qobj.q; # pop_event(EventQueue* q, output int& id, output double& t); @ @eventq/push.m ------------------------------------- function push(qobj, id, t) $ void push_events(EventQueue* q, int* id, double* t, int m) $ { $ for (int i = 0; i < m; ++i) $ q->push(Event(t[i], id[i])); $ } $ q = qobj.q; m = length(id); # push_events(EventQueue* q, int[m] id, double[m] t, int m); mwrap-1.1.1/example/eventq/eventq_handle.mw000066400000000000000000000026201430266125200207600ustar00rootroot00000000000000% eventq_handle.mw % Simple event queue for use in MATLAB event-driven simulations. % Uses the MATLAB 2008+ OO system for encapsulating the event queue. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $ #include $ $ typedef std::pair Event; $ typedef std::priority_queue< Event, $ std::vector, $ std::greater > EventQueue; @ eventqh.m -------------------------------------------- classdef eventqh < handle properties mwptr end methods function [qobj] = eventqh() # EventQueue* q = new EventQueue(); qobj.mwptr = q; end function delete(q) #delete(EventQueue* q); end function e = empty(q) # int e = q->EventQueue.empty(); end function [id, t] = pop(q) $ void pop_event(EventQueue* q, int& id, double& t) { $ t = q->top().first; $ id = q->top().second; $ q->pop(); $ } # pop_event(EventQueue* q, output int& id, output double& t); end function push(q, id, t) $ void push_events(EventQueue* q, int* id, double* t, int m) $ { $ for (int i = 0; i < m; ++i) $ q->push(Event(t[i], id[i])); $ } m = length(id); # push_events(EventQueue* q, int[m] id, double[m] t, int m); end end end mwrap-1.1.1/example/eventq/eventq_plain.mw000066400000000000000000000020671430266125200206350ustar00rootroot00000000000000% eventq_plain.mw % Simple event queue for use in MATLAB event-driven simulations. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $[ #include typedef std::pair Event; typedef std::priority_queue< Event, std::vector, std::greater > EventQueue; $] @function [q] = EventQ_new(); # EventQueue* q = new EventQueue(); @function EventQ_destroy(q); # delete(EventQueue* q); @function [e] = EventQ_empty(q) # int e = q->EventQueue.empty(); @function [id, t] = EventQ_pop(q) $ void pop_event(EventQueue* q, int& id, double& t) { $ t = q->top().first; $ id = q->top().second; $ q->pop(); $ } $ # pop_event(EventQueue* q, output int& id, output double& t); @function EventQ_push(q, id, t) $ void push_events(EventQueue* q, int* id, double* t, int m) $ { $ for (int i = 0; i < m; ++i) $ q->push(Event(t[i], id[i])); $ } $ m = length(id); # push_events(EventQueue* q, int[m] id, double[m] t, int m); mwrap-1.1.1/example/eventq/testq_class.m000066400000000000000000000006671430266125200203120ustar00rootroot00000000000000% testq_class.m % Test case / demo of MWrap bindings to a C++ event queue class. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions if ~exist('isobject') fprintf('MATLAB object system not supported\n'); return; end q = eventq(); push(q, 1, 1.5); push(q, 2, 0.4); push(q, 3, 10); push(q, [4, 5], [8, 11]); while ~empty(q) [id,t] = pop(q); fprintf('Time %g: Saw %d\n', t, id); end destroy(q); mwrap-1.1.1/example/eventq/testq_handle.m000066400000000000000000000007111430266125200204260ustar00rootroot00000000000000% testq_class.m % Test case / demo of MWrap bindings to a C++ event queue class. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions if ~exist('ishandle') | ~exist('isobject') fprintf('MATLAB object system not supported\n'); return; end q = eventqh(); push(q, 1, 1.5); push(q, 2, 0.4); push(q, 3, 10); push(q, [4, 5], [8, 11]); while ~empty(q) [id,t] = pop(q); fprintf('Time %g: Saw %d\n', t, id); end clear q mwrap-1.1.1/example/eventq/testq_plain.m000066400000000000000000000006241430266125200203010ustar00rootroot00000000000000% testq_plain.m % Test case / demo of MWrap bindings to a C++ event queue class. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions q = EventQ_new(); EventQ_push(q, 1, 1.5); EventQ_push(q, 2, 0.4); EventQ_push(q, 3, 10); EventQ_push(q, [4, 5], [8, 11]); while ~EventQ_empty(q) [id,t] = EventQ_pop(q); fprintf('Time %g: Saw %d\n', t, id); end EventQ_destroy(q); mwrap-1.1.1/example/eventq2/000077500000000000000000000000001430266125200156605ustar00rootroot00000000000000mwrap-1.1.1/example/eventq2/Makefile000066400000000000000000000002571430266125200173240ustar00rootroot00000000000000include ../../make.inc MW=../../mwrap mex: $(MW) -mex eventq2mex -c eventq2mex.cc -mb eventq2.mw $(MEX) eventq2mex.cc clean: rm -f EventQ_*.m rm -f eventq2mex.* *.o *~ mwrap-1.1.1/example/eventq2/README000066400000000000000000000004631430266125200165430ustar00rootroot00000000000000Example of bindings using the mxArray wrapper. In this case, we wrap an STL priority queue of (mxArray, time) pairs. This is a variant of the event queue example in the example/eventq subdirectory, except in this version we can store arbitrary MATLAB data objects in the queue, rather than just integers. mwrap-1.1.1/example/eventq2/eventq2.mw000066400000000000000000000023531430266125200176140ustar00rootroot00000000000000% eventq_plain.mw % Simple event queue for use in MATLAB event-driven simulations. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $[ #include #include typedef std::pair Event; typedef std::priority_queue< Event, std::vector, std::greater > EventQueue; $] // ---- @function [q] = EventQ_new(); # EventQueue* q = new EventQueue(); // ---- @function EventQ_destroy(q); while ~EventQ_empty(q) EventQ_pop(q) end # delete(EventQueue* q); // ---- @function [e] = EventQ_empty(q) # int e = q->EventQueue.empty(); // ---- @function [data, t] = EventQ_pop(q) $[ mxArray* pop_event(EventQueue* q, double& t) { t = q->top().first; mxArray* data = mxDuplicateArray(q->top().second); mxDestroyArray(q->top().second); q->pop(); return data; } $] # mxArray data = pop_event(EventQueue* q, output double& t); // ---- @function EventQ_push(q, data, t) $[ void push_event(EventQueue* q, const mxArray* a, double t) { mxArray* data = mxDuplicateArray(a); mexMakeArrayPersistent(data); q->push(Event(t, data)); } $] # push_event(EventQueue* q, mxArray data, double t); mwrap-1.1.1/example/eventq2/testq2.m000066400000000000000000000006501430266125200172610ustar00rootroot00000000000000% testq_plain.m % Test case / demo of MWrap bindings to a C++ event queue class. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions q = EventQ_new(); EventQ_push(q, 1, 1.5); EventQ_push(q, 2, 0.4); EventQ_push(q, 3, 10); EventQ_push(q, 'Mary had a little lamb', 8); while ~EventQ_empty(q) [data,t] = EventQ_pop(q); fprintf('Time %g: Saw ', t); disp(data); end EventQ_destroy(q); mwrap-1.1.1/example/fem/000077500000000000000000000000001430266125200150435ustar00rootroot00000000000000mwrap-1.1.1/example/fem/Makefile000066400000000000000000000002571430266125200165070ustar00rootroot00000000000000all: mkdir -p mwfem (cd src; make) (cd interface; make) clean: (cd src; make clean) (cd interface; make clean) rm -rf mwfem realclean: clean (cd src; make realclean) mwrap-1.1.1/example/fem/README000066400000000000000000000007071430266125200157270ustar00rootroot00000000000000This example illustrates several features of MWrap: - The binding to the finite element assembly class uses mxArrays directly (for sparse matrices). - The binding to element types uses inheritance. - The bindings to the mesh methods illustrate using zero-based to one-based construction. The finite element source files are in src; the MWrap input files are in interface. The MEX file and generated .m files build into the mwfem subdirectory. mwrap-1.1.1/example/fem/init.m000066400000000000000000000000621430266125200161620ustar00rootroot00000000000000if ~exist('femex'), addpath([pwd, '/mwfem']); end mwrap-1.1.1/example/fem/interface/000077500000000000000000000000001430266125200170035ustar00rootroot00000000000000mwrap-1.1.1/example/fem/interface/Makefile000066400000000000000000000003301430266125200204370ustar00rootroot00000000000000include ../../../make.inc MW=../../../mwrap mex: wrap $(MEX) -I../src femex.cc ../src/*.o mv femex.* *.m ../mwfem wrap: $(MW) -mex femex -c femex.cc \ -mb assembler.mw mesh.mw elements.mw clean: rm -f *~ mwrap-1.1.1/example/fem/interface/assembler.mw000066400000000000000000000041521430266125200213270ustar00rootroot00000000000000% assembler.mw % MWrap bindings for MatrixAssembler (CSC matrix assembly). % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $[ #include "assembler.h" #include #include mxArray* export_matrix(MatrixAssembler* matrix) { matrix->compress(); int m = matrix->get_m(); int n = matrix->get_n(); int nnz = matrix->csc_nnz(); mxArray* result = mxCreateSparse(m, n, nnz, mxREAL); std::copy(matrix->get_jc(), matrix->get_jc()+n+1, mxGetJc(result)); std::copy(matrix->get_ir(), matrix->get_ir()+nnz, mxGetIr(result)); std::copy(matrix->get_pr(), matrix->get_pr()+nnz, mxGetPr(result)); return result; } $] @function aobj = Assembler_create(m, n, nnz) % aobj = Assembler_create(m, n) % % Create an assembly object for m-by-n matrices. if nargin < 2, m = n; end if nargin < 3 # MatrixAssembler* aobj = new MatrixAssembler(int m, int n); else # MatrixAssembler* aobj = new MatrixAssembler(int m, int n, int nnz); end @function Assembler_delete(aobj) % Assembler_delete(aobj) % % Delete a matrix assembler object # delete(MatrixAssembler* aobj); @function Assembler_add(aobj, ii, jj, Aelt) % Assembler_create(aobj, ii, jj, Aelt) % % Perform A(ii,jj) += Aelt. [m,n] = size(Aelt); ii = ii-1; jj = jj-1; # aobj->MatrixAssembler.add_entry(int[m] ii, int[n] jj, double[m,n] Aelt, # int m, int n); @function K = Assembler_get(aobj) % K = Assembler_get(aobj) % % Retrieve a sparse matrix from a matrix assembler. # mxArray K = export_matrix(MatrixAssembler* aobj); @function Assembler_clear(aobj) % Assembler_clear(aobj) % % Clear the matrix assembler in preparation for building a new matrix. # aobj->MatrixAssembler.wipe(); @function [structure_nnz, cached_nnz] = Assembler_stats(aobj) % [structure_nnz, cached_nnz] = Assembler_stats(aobj) % % Get statistics about the nonzeros in the assembler. # int structure_nnz = aobj->MatrixAssembler.csc_nnz(); # int cached_nnz = aobj->MatrixAssembler.cache_nnz(); if nargout == 0 fprintf('NNZ in structure: %d\n', structure_nnz); fprintf('NNZ in cache: %d\n', cached_nnz); end mwrap-1.1.1/example/fem/interface/elements.mw000066400000000000000000000020271430266125200211650ustar00rootroot00000000000000% elements.mw % MWrap bindings for element types. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $[ #include "mesh.h" #include "scalar1d.h" #include "scalar2d.h" #include "elastic2d.h" $] # class Scalar1D : EType; # class Scalar2D : EType; # class Elastic2D : EType; @function etype = Mesh_add_scalar1d(mobj, k) % material = Mesh_add_scalar1d(mobj, k) % % Add a simple scalar element type to the mesh object. # Scalar1D* etype = new Scalar1D(double k); # mobj->Mesh.add_material(EType* etype); @function etype = Mesh_add_scalar2d(mobj, k) % material = Mesh_add_scalar2d(mobj, k) % % Add a simple scalar element type to the mesh object. # Scalar2D* etype = new Scalar2D(double k); # mobj->Mesh.add_material(EType* etype); @function etype = Mesh_add_elastic2d(mobj, E, nu, which) % material = Mesh_add_elastic2d(mobj, E, nu, which) % % Add a plane strain elastic element type to the mesh. # Elastic2D* etype = new Elastic2D(double E, double nu, cstring which); # mobj->Mesh.add_material(EType* etype); mwrap-1.1.1/example/fem/interface/mesh.mw000066400000000000000000000202511430266125200203040ustar00rootroot00000000000000% mesh.mw % MWrap bindings for Mesh. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $ #include "mesh.h" // ---- @function mobj = Mesh_create(ndm, maxndf, maxnen) % mobj = Mesh_create(ndm, maxndf, maxnen) % % Create a new mesh object. % ndm - Number of spatial dimensions % maxndf - Maximum number of dofs per node % maxnen - Maximum number of elements per node # Mesh* mobj = new Mesh(int ndm, int maxndf, int maxnen); // ---- @function Mesh_delete(mobj) % Mesh_delete(mobj) % % Delete an existing mesh object. # delete(Mesh* mobj); // ---- @function ndm = Mesh_ndm(mobj) % ndm = Mesh_ndm(mobj) % % Get the number of spatial dimensions for the mesh # int ndm = mobj->Mesh.ndm(); // ---- @function maxndf = Mesh_maxndf(mobj) % maxndf = Mesh_maxndf(mobj) % % Get the maximum number of nodal dofs for the mesh # int maxndf = mobj->Mesh.maxndf(); // ---- @function maxnen = Mesh_maxnen(mobj) % maxnen = Mesh_maxnen(mobj) % % Get the maximum number of nodes per element for the mesh # int maxnen = mobj->Mesh.maxnen(); // ---- @function numelt = Mesh_numelt(mobj) % numelt = Mesh_numelt(mobj) % % Get the number of elements in the mesh. # int numelt = mobj->Mesh.numelt(); // ---- @function numnp = Mesh_numnp(mobj) % numnp = Mesh_numnp(mobj) % % Get the number of nodes in the mesh # int numnp = mobj->Mesh.numnp(); // ---- @function numid = Mesh_numid(mobj) % numid = Mesh_numid(mobj) % % Get the number of active dofs in the mesh # int numid = mobj->Mesh.numid(); // ---- @function x = Mesh_x(mobj, i) % Mesh_x(mobj, i) % % Get the coordinates of mesh node i. If the node number is omitted, % get the coordinates for all nodes in the mesh. if nargin == 2 i = i-1; # int ndm = mobj->Mesh.ndm(); # double[ndm] x = mobj->Mesh.x(int i); else # int numnp = mobj->Mesh.numnp(); # int ndm = mobj->Mesh.ndm(); # double[ndm,numnp] x = mobj->Mesh.x(); end // ---- @function ix = Mesh_ix(mobj, i) % Mesh_ix(mobj, i) % % Get the connectivity of element i. If the element number is omitted, % get the connectivity for all elements in the mesh. if nargin == 2 i = i-1; # int maxnen = mobj->Mesh.maxndf(); # int[maxnen] ix = mobj->Mesh.ix(int i); else # int numelt = mobj->Mesh.numelt(); # int maxnen = mobj->Mesh.maxnen(); # int[maxnen,numelt] ix = mobj->Mesh.ix(); end ix = ix+1; // ---- @function id = Mesh_id(mobj, i) % Mesh_id(mobj, i) % % Get the degrees of freedom for element i. If the element number is omitted, % get the degrees of freedom for all elements in the mesh. if nargin == 2 i = i - 1; # int maxndf = mobj->Mesh.maxndf(); # int[maxndf] id = mobj->Mesh.id(int i); else # int numnp = mobj->Mesh.numnp(); # int maxndf = mobj->Mesh.maxndf(); # int[maxndf,numnp] id = mobj->Mesh.id(); end id = id + 1; // ---- @function u = Mesh_u(mobj, i) % Mesh_u(mobj, i) % % Get the displacement of mesh node i. If the node number is omitted, % get the displacements for all nodes in the mesh. if nargin == 2 i = i-1; # int maxndf = mobj->Mesh.maxndf(); # double[maxndf] u = mobj->Mesh.u(int i); else # int numnp = mobj->Mesh.numnp(); # int maxndf = mobj->Mesh.maxndf(); # double[maxndf,numnp] u = mobj->Mesh.u(); end // ---- @function f = Mesh_f(mobj, i) % Mesh_f(mobj, i) % % Get the forces for mesh node i. If the node number is omitted, % get the forces for all nodes in the mesh. if nargin == 2 i = i-1; # int maxndf = mobj->Mesh.maxndf(); # double[maxndf] f = mobj->Mesh.f(int i); else # int numnp = mobj->Mesh.numnp(); # int maxndf = mobj->Mesh.maxndf(); # double[maxndf,numnp] f = mobj->Mesh.f(); end // ---- @function bc = Mesh_bc(mobj, i) % Mesh_bc(mobj, i) % % Get the boundary codes of mesh node i. If the node number is omitted, % get the boundary codes for all nodes in the mesh. if nargin == 2 i = i-1; # int maxndf = mobj->Mesh.maxndf(); # char[maxndf] bc = mobj->Mesh.bc(int i); else # int numnp = mobj->Mesh.numnp(); # int maxndf = mobj->Mesh.maxndf(); # char[maxndf,numnp] bc = mobj->Mesh.bc(); end // ---- @function bv = Mesh_bv(mobj, i) % Mesh_bv(mobj, i) % % Get the boundary values of mesh node i. If the node number is omitted, % get the boundary values for all nodes in the mesh. if nargin == 2 i = i-1; # int maxndf = mobj->Mesh.maxndf(); # double[maxndf] bv = mobj->Mesh.bv(int i); else # int numnp = mobj->Mesh.numnp(); # int maxndf = mobj->Mesh.maxndf(); # double[maxndf,numnp] bv = mobj->Mesh.bv(); end // ---- @function Mesh_set_ur(mobj, ur) % Mesh_set_ur(mobj, ur) % % Set reduced displacement vector numid = Mesh_numid(mobj); # mobj->Mesh.set_ur(input double[numid] ur); // ---- @function ur = Mesh_get_ur(mobj) % ur = Mesh_get_ur(mobj) % % Get reduced displacement vector numid = Mesh_numid(mobj); # mobj->Mesh.get_ur(output double[numid] ur); // ---- @function Mesh_set_bc(mobj, bc, i, j) % Mesh_set_bc(mobj, bc, i, j) % % Set the boundary codes of mesh node i. If the node number is omitted, % set the boundary codes for all nodes in the mesh. $[ void set_bc(Mesh* mesh, char bc, int i, int j) { mesh->bc(i,j) = bc; } void set_bc(Mesh* mesh, char* bc) { int numnp = mesh->numnp(); int maxndf = mesh->maxndf(); for (int j = 0; j < numnp; ++j) for (int i = 0; i < maxndf; ++i) mesh->bc(i,j) = bc[i+j*maxndf]; } $] if nargin == 4 i = i-1; j = j-1; # int maxndf = mobj->Mesh.maxndf(); # set_bc(Mesh* mobj, char bc, int i, int j); else # int numnp = mobj->Mesh.numnp(); # int maxndf = mobj->Mesh.maxndf(); # set_bc(Mesh* mobj, char[maxndf,numnp] bc); end // ---- @function Mesh_set_bv(mobj, bv, i, j) % Mesh_set_bv(mobj, bv, i, j) % % Set the boundary codes of mesh node i. If the node number is omitted, % set the boundary codes for all nodes in the mesh. $[ void set_bv(Mesh* mesh, double bv, int i, int j) { mesh->bv(i,j) = bv; } void set_bv(Mesh* mesh, double* bv) { int numnp = mesh->numnp(); int maxndf = mesh->maxndf(); for (int j = 0; j < numnp; ++j) for (int i = 0; i < maxndf; ++i) mesh->bv(i,j) = bv[i+j*maxndf]; } $] if nargin == 4 i = i-1; j = j-1; # int maxndf = mobj->Mesh.maxndf(); # set_bv(Mesh* mobj, double bv, int i, int j); else # int numnp = mobj->Mesh.numnp(); # int maxndf = mobj->Mesh.maxndf(); # set_bv(Mesh* mobj, double[maxndf,numnp] bv); end // ---- @function numid = Mesh_initialize(mobj) % numid = Mesh_initialize(mobj) % % Initialize the mesh object after completion of X/IX arrays. # int numid = mobj->Mesh.initialize(); // ---- @function numid = Mesh_assign_ids(mobj) % numid = Mesh_assign_ids(mobj) % % Assign identifiers to active degrees of freedom in the mesh. # int numid = mobj->Mesh.assign_ids(); // ---- @function F = Mesh_assemble_F(mobj) % F = Mesh_assemble_F(mobj) % % Assemble system residual force vector. numid = Mesh_numid(mobj); # mobj->Mesh.assemble_F(); # mobj->Mesh.get_fr(output double[numid] F); // ---- @function K = Mesh_assemble_K(mobj) % K = Mesh_assemble_K(mobj) % % Assemble system stiffness matrix. numid = Mesh_numid(mobj); Ka = Assembler_create(numid, numid); # mobj->Mesh.assemble_K(MatrixAssembler* Ka); K = Assembler_get(Ka); Assembler_delete(Ka); // ---- @function id = Mesh_add_node(mobj, x) % id = Mesh_add_node(mobj, x) % % Build a new node at position x and return the index. # int ndm = mobj->Mesh.ndm(); # int id = mobj->Mesh.add_node(double[ndm] x); id = id + 1; // ---- @function id = Mesh_add_element(mobj, etype, nodes) % id = Mesh_add_element(mobj, etype, nodes) % % Build a new element of type etype connected to the indicated nodes, % and return the index. numnp = length(nodes); nodes = nodes-1; # int id = mobj->Mesh.add_element(EType* etype, int[numnp] nodes, int numnp); id = id + 1; // ---- @function Mesh_load(mobj, etype, x, ix) % Mesh_load(mobj, material, x, ix) % % Add a new batch of elements % material - Material type % x - Coordinates of nodes in new elements % ix - Connectivity array for new elements # int ndm = mobj->Mesh.ndm(); ids = zeros(1,size(x,2)); for j = 1:size(x,2) xj = x(:,j); # int id = mobj->Mesh.add_node(double[ndm] xj); ids(j) = id; end numnp = size(ix,1); for j = 1:size(ix,2) ixj = ids(ix(:,j)); # int id = mobj->Mesh.add_element(EType* etype, int[numnp] ixj, int numnp); end mwrap-1.1.1/example/fem/src/000077500000000000000000000000001430266125200156325ustar00rootroot00000000000000mwrap-1.1.1/example/fem/src/Makefile000066400000000000000000000006761430266125200173030ustar00rootroot00000000000000# Targets for object files (we compile with MEX to avoid headaches # about -fPIC and other flag compatibility issues) include ../../../make.inc OBJS= \ assembler.o mesh.o \ gauss2by2.o quad2d1.o \ scalar1d.o scalar2d.o elastic2d1.o all: $(OBJS) .cc.o: $(MEX) -c $*.cc elastic2d1.cc: matexpr elastic2d.cc > elastic2d1.cc quad2d1.cc: matexpr quad2d.cc > quad2d1.cc clean: rm -f *.o *~ realclean: rm -f *.o elastic2d1.cc quad2d1.cc mwrap-1.1.1/example/fem/src/assembler.cc000066400000000000000000000060071430266125200201210ustar00rootroot00000000000000/* * assembler.cc * Compressed sparse column matrix assembler implementation. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "assembler.h" #include #include #define ME MatrixAssembler using std::sort; using std::fill; /* * Add A(i,j) += Aij. If there's space in the existing compressed * sparse column data structure, add it there; otherwise, stash it in * the coords cache vector. */ void ME::add_entry(int i, int j, double Aij) { if (i < 0 || i >= m || j < 0 || j >= n) return; for (int ii = jc[j]; ii < jc[j+1]; ++ii) { if (ir[ii] == i) { pr[ii] += Aij; return; } } coords.push_back(Coord(i,j,Aij)); } /* * Add an element submatrix. */ void ME::add_entry(const int* i, const int* j, double* Aij, int m_elt, int n_elt) { for (int jj = 0; jj < n_elt; ++jj) for (int ii = 0; ii < m_elt; ++ii) add_entry(i[ii], j[jj], Aij[jj*m_elt+ii]); } /* * Wipe the input matrix. Note that the compressed sparse column index * structure remains intact, so we can re-assemble without doing too much * work. */ void ME::wipe() { coords.resize(0); fill(get_pr(), get_pr()+jc[n], 0); } /* * Sort the entries in the coords cache, and merge (by summing) contributions * to the same position. */ void ME::pack_cache() { if (coords.size() > 0) { sort(coords.begin(), coords.end()); int i_merge = 0; for (int i_coord = 1; i_coord < coords.size(); ++i_coord) { if (coords[i_merge] < coords[i_coord]) coords[++i_merge] = coords[i_coord]; else coords[i_merge].Aij += coords[i_coord].Aij; } coords.resize(i_merge+1); } } /* * Pack the coordinate cache, then merge sort the contents of the compressed * sparse column data structure with the contents of the entry cache. */ void ME::compress() { pack_cache(); ir.resize(ir.size() + coords.size()); pr.resize(pr.size() + coords.size()); int i_coord = coords.size()-1; // Next input coord to process int i_csc = jc[n]-1; // Next input CSC entry to process int i_merge = pr.size()-1; // Next output CSC entry to process jc[n] = pr.size(); for (int j = n; j > 0; --j) { // Merge column from cache with column from previous CSC while (i_coord >= 0 && coords[i_coord].j == j-1 && i_csc >= 0 && i_csc >= jc[j-1]) { if (coords[i_coord].i > ir[i_csc]) { ir[i_merge] = coords[i_coord].i; pr[i_merge] = coords[i_coord].Aij; --i_coord; } else { ir[i_merge] = ir[i_csc]; pr[i_merge] = pr[i_csc]; --i_csc; } --i_merge; } // Copy stragglers from coord list while (i_coord >= 0 && coords[i_coord].j == j-1) { ir[i_merge] = coords[i_coord].i; pr[i_merge] = coords[i_coord].Aij; --i_coord; --i_merge; } // Copy stragglers from CSC list while (i_csc >= 0 && i_csc >= jc[j-1]) { ir[i_merge] = ir[i_csc]; pr[i_merge] = pr[i_csc]; --i_csc; --i_merge; } // Update the column count jc[j-1] = i_merge+1; } coords.resize(0); } mwrap-1.1.1/example/fem/src/assembler.h000066400000000000000000000051071430266125200177630ustar00rootroot00000000000000/* * assembler.h * Compressed sparse column matrix assembler interface. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef ASSEMBLER_H #define ASSEMBLER_H #include using std::vector; /* * The MatrixAssembler class is responsible for assembling a finite element * matrix. In pure MATLAB, the assembly operation looks something like * * for i = 1:num_elements * [Ke, idx] = element_stiffness(i); * Ivalid = find(idx > 0 & idx < N); * idx = idx(Ivalid); * Ke = Ke(Ivalid,Ivalid); * K(idx,idx) = K(idx,idx) + Ke; * end * * The method add_entry is equivalent to most of the body of this loop -- * it removes out-of-range indices and accumulates the rest of the element * contribution. * * Elements in the matrix can be stored in one of two ways. First, * there are elements that go into the current compressed sparse * column matrix structure. Then there are elements that correspond * to indices that were not in the matrix the last time we built the * compressed sparse column structure. When it is time to assemble * the matrix, we use the compress method to take all these extra * elements and merge them into the compressed sparse column indexing * structure. This means that after K is assembled once, any we can * assemble other matrices with the same structure using a little less * time and memory. */ class MatrixAssembler { public: MatrixAssembler(int m, int n) : m(m), n(n), jc(n+1) {} MatrixAssembler(int m, int n, int coord_nnz) : m(m), n(n), jc(n+1), coords(coord_nnz) {} void add_entry(int i, int j, double Aij); void add_entry(const int* i, const int* j, double* Aij, int m_elt, int n_elt); void wipe(); void pack_cache(); void compress(); int get_m() { return m; } int get_n() { return n; } int* get_jc() { return &(jc[0]); } int* get_ir() { return &(ir[0]); } double* get_pr() { return &(pr[0]); } int cache_nnz() { return coords.size(); } int csc_nnz() { return pr.size(); } private: struct Coord { Coord() {} Coord(int i, int j, double Aij) : i(i), j(j), Aij(Aij) {} bool operator<(const Coord& coord) const { return ((j < coord.j) || (j == coord.j && i < coord.i)); } int i, j; double Aij; }; int m, n; // Things that fit in the compressed sparse representation vector jc; vector ir; vector pr; // Cache of entries that didn't fit in the compressed sparse form vector coords; }; #endif /* ASSEMBLER_H */ mwrap-1.1.1/example/fem/src/assembler2.cc000066400000000000000000000060101430266125200201750ustar00rootroot00000000000000/* * assembler.cc * Compressed sparse column matrix assembler implementation. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "assembler.h" #include #include #define ME MatrixAssembler2 using std::sort; using std::fill; /* * Add A(i,j) += Aij. If there's space in the existing compressed * sparse column data structure, add it there; otherwise, stash it in * the coords cache vector. */ void ME::add_entry(int i, int j, double Aij) { if (i < 0 || i >= m || j < 0 || j >= n) return; for (int ii = jc[j]; ii < jc[j+1]; ++ii) { if (ir[ii] == i) { pr[ii] += Aij; return; } } coords.push_back(Coord(i,j,Aij)); } /* * Add an element submatrix. */ void ME::add_entry(const int* i, const int* j, double* Aij, int m_elt, int n_elt) { for (int jj = 0; jj < n_elt; ++jj) for (int ii = 0; ii < m_elt; ++ii) add_entry(i[ii], j[jj], Aij[jj*m_elt+ii]); } /* * Wipe the input matrix. Note that the compressed sparse column index * structure remains intact, so we can re-assemble without doing too much * work. */ void ME::wipe() { coords.resize(0); fill(get_pr(), get_pr()+jc[n], 0); } /* * Sort the entries in the coords cache, and merge (by summing) contributions * to the same position. */ void ME::pack_cache() { if (coords.size() > 0) { sort(coords.begin(), coords.end()); int i_merge = 0; for (int i_coord = 1; i_coord < coords.size(); ++i_coord) { if (coords[i_merge] < coords[i_coord]) coords[++i_merge] = coords[i_coord]; else coords[i_merge].Aij += coords[i_coord].Aij; } coords.resize(i_merge+1); } } /* * Pack the coordinate cache, then merge sort the contents of the compressed * sparse column data structure with the contents of the entry cache. */ void ME::compress() { pack_cache(); ir.resize(ir.size() + coords.size()); pr.resize(pr.size() + coords.size()); int i_coord = coords.size()-1; // Next input coord to process int i_csc = jc[n]-1; // Next input CSC entry to process int i_merge = pr.size()-1; // Next output CSC entry to process jc[n] = pr.size(); for (int j = n; j > 0; --j) { // Merge column from cache with column from previous CSC while (i_coord >= 0 && coords[i_coord].j == j-1 && i_csc >= 0 && i_csc >= jc[j-1]) { if (coords[i_coord].i > ir[i_csc]) { ir[i_merge] = coords[i_coord].i; pr[i_merge] = coords[i_coord].Aij; --i_coord; } else { ir[i_merge] = ir[i_csc]; pr[i_merge] = pr[i_csc]; --i_csc; } --i_merge; } // Copy stragglers from coord list while (i_coord >= 0 && coords[i_coord].j == j-1) { ir[i_merge] = coords[i_coord].i; pr[i_merge] = coords[i_coord].Aij; --i_coord; --i_merge; } // Copy stragglers from CSC list while (i_csc >= 0 && i_csc >= jc[j-1]) { ir[i_merge] = ir[i_csc]; pr[i_merge] = pr[i_csc]; --i_csc; --i_merge; } // Update the column count jc[j-1] = i_merge+1; } coords.resize(0); } mwrap-1.1.1/example/fem/src/assembler2.h000066400000000000000000000051121430266125200200410ustar00rootroot00000000000000/* * assembler.h * Compressed sparse column matrix assembler interface. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef ASSEMBLER2_H #define ASSEMBLER2_H #include using std::vector; /* * The MatrixAssembler2 class is responsible for assembling a finite element * matrix. In pure MATLAB, the assembly operation looks something like * * for i = 1:num_elements * [Ke, idx] = element_stiffness(i); * Ivalid = find(idx > 0 & idx < N); * idx = idx(Ivalid); * Ke = Ke(Ivalid,Ivalid); * K(idx,idx) = K(idx,idx) + Ke; * end * * The method add_entry is equivalent to most of the body of this loop -- * it removes out-of-range indices and accumulates the rest of the element * contribution. * * Elements in the matrix can be stored in one of two ways. First, * there are elements that go into the current compressed sparse * column matrix structure. Then there are elements that correspond * to indices that were not in the matrix the last time we built the * compressed sparse column structure. When it is time to assemble * the matrix, we use the compress method to take all these extra * elements and merge them into the compressed sparse column indexing * structure. This means that after K is assembled once, we can * assemble other matrices with the same structure using a little less * time and memory. */ class MatrixAssembler2 { public: MatrixAssembler2(int m, int n) : m(m), n(n), jc(n+1) {} MatrixAssembler2(int m, int n, int coord_nnz) : m(m), n(n), jc(n+1), coords(coord_nnz) {} void add_entry(int i, int j, double Aij); void add_entry(const int* i, const int* j, double* Aij, int m_elt, int n_elt); void wipe(); void pack_cache(); void compress(); int get_m() { return m; } int get_n() { return n; } int* get_jc() { return &(jc[0]); } int* get_ir() { return &(ir[0]); } double* get_pr() { return &(pr[0]); } int cache_nnz() { return coords.size(); } int csc_nnz() { return pr.size(); } private: struct Coord { Coord() {} Coord(int i, int j, double Aij) : i(i), j(j), Aij(Aij) {} bool operator<(const Coord& coord) const { return ((j < coord.j) || (j == coord.j && i < coord.i)); } int i, j; double Aij; }; int m, n; // Things that fit in the compressed sparse representation vector jc; vector ir; vector pr; // Cache of entries that didn't fit in the compressed sparse form vector coords; }; #endif /* ASSEMBLER2_H */ mwrap-1.1.1/example/fem/src/elastic2d.cc000066400000000000000000000073051430266125200200200ustar00rootroot00000000000000/* * elastic2d.cc * Element type for 2D elasticity (4 node quad only). * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "etype.h" #include "mesh.h" #include "elastic2d.h" #include "quad2d.h" #include "gauss2by2.h" #include #define ME Elastic2D ME::ME(double E, double nu, const char* type) { if (strcmp(type, "plane stress") == 0) plane_stress(E, nu); else plane_strain(E, nu); } void ME::plane_strain(double E, double nu) { /* input E, nu; output D(3,3); D = E/(1+nu)/(1-2*nu) * [ 1-nu, nu, 0; nu, 1-nu, 0; 0, 0, (1-2*nu)/2 ]; */ } void ME::plane_stress(double E, double nu) { /* input E, nu; output D(3,3); D = E/(1-nu*nu) * [ 1, nu, 0; nu, 1, 0; 0, 0, (1-nu)/2 ]; */ } void ME::assign_ids(Mesh* mesh, int eltid) { for (int i = 0; i < 4; ++i) { int ni = mesh->ix(i,eltid); mesh->id(0,ni) = 1; mesh->id(1,ni) = 1; } } void ME::assemble_f(Mesh* mesh, int eltid) { Quad2d quad; Gauss4 xi(quad); get_quad(quad, mesh, eltid); vector K(4*4); for (xi.start(); !xi.done(); ++xi) { double eps[3] = {0, 0, 0}; for (int j = 0; j < 4; ++j) { const double* u = mesh->u(mesh->ix(j,eltid)); double Nj_x = xi.dN(j,0); double Nj_y = xi.dN(j,1); /* // Contribute strain at quadrature point input Nj_x, Nj_y, D(3,3); inout eps(3); input u(2); Bj = [Nj_x, 0; 0, Nj_y; Nj_y, Nj_x]; eps += Bj*u; */ } for (int i = 0; i < 4; ++i) { double* f = mesh->f(mesh->ix(i,eltid)); double Ni_x = xi.dN(i,0); double Ni_y = xi.dN(i,1); double w = xi.wt(); /* // Contribute B_i'*D*B(u) * w input Ni_x, Ni_y, D(3,3), w; input eps(3); inout f(2); Bi = [Ni_x, 0; 0, Ni_y; Ni_y, Ni_x]; f += Bi'*D*eps*w; */ } } } void ME::assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler) { Quad2d quad; Gauss4 xi(quad); get_quad(quad, mesh, eltid); vector K(8*8); for (xi.start(); !xi.done(); ++xi) { double w = xi.wt(); for (int j = 0; j < 4; ++j) { double Nj_x = xi.dN(j,0); double Nj_y = xi.dN(j,1); for (int i = 0; i < 4; ++i) { double Ni_x = xi.dN(i,0); double Ni_y = xi.dN(i,1); double* Knodal = &(K[16*j +2*i+ 0]); /* // B-matrix based displacement formulation // Isotropic plane strain constitutive tensor input D(3,3), w; input Ni_x, Ni_y, Nj_x, Nj_y; inout Knodal[8](2,2); Bi = [Ni_x, 0; 0, Ni_y; Ni_y, Ni_x]; Bj = [Nj_x, 0; 0, Nj_y; Nj_y, Nj_x]; Knodal += Bi'*D*Bj * w; */ } } } K_assembler->add_entry(id, id, &(K[0]), 8, 8); } void ME::get_quad(FEShapes& quad, Mesh* mesh, int eltid) { for (int i = 0; i < 4; ++i) { int n = mesh->ix(i,eltid); quad.set_node(i, mesh->x(n)); id[2*i+0] = mesh->id(0,n); id[2*i+1] = mesh->id(1,n); } } mwrap-1.1.1/example/fem/src/elastic2d.h000066400000000000000000000013701430266125200176560ustar00rootroot00000000000000/* * elastic2d.h * Element type for 2D elasticity * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef ELASTIC2D_H #define ELASTIC2D_H #include "etype.h" #include "mesh.h" #include "feshapes.h" class Elastic2D : public EType { public: Elastic2D(double E, double nu, const char* type = "plane strain"); void assign_ids(Mesh* mesh, int eltid); void assemble_f(Mesh* mesh, int eltid); void assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler); private: double D[9]; int id[8]; void plane_strain(double E, double nu); void plane_stress(double E, double nu); void get_quad(FEShapes& quad, Mesh* mesh, int eltid); }; #endif /* ELASTIC2D_H */ mwrap-1.1.1/example/fem/src/elastic2d1.cc000066400000000000000000000250111430266125200200730ustar00rootroot00000000000000/* * elastic2d.cc * Element type for 2D elasticity (4 node quad only). * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "etype.h" #include "mesh.h" #include "elastic2d.h" #include "quad2d.h" #include "gauss2by2.h" #include #define ME Elastic2D ME::ME(double E, double nu, const char* type) { if (strcmp(type, "plane stress") == 0) plane_stress(E, nu); else plane_strain(E, nu); } void ME::plane_strain(double E, double nu) { /* input E, nu; output D(3,3); D = E/(1+nu)/(1-2*nu) * [ 1-nu, nu, 0; nu, 1-nu, 0; 0, 0, (1-2*nu)/2 ]; */ /* */ { double tmp1_ = E; double tmp2_ = nu; double tmp4_ = 1.0 + tmp2_; double tmp5_ = tmp1_ / tmp4_; double tmp7_ = 2.0 * tmp2_; double tmp8_ = 1.0 - tmp7_; double tmp9_ = tmp5_ / tmp8_; double tmp10_ = 1.0 - tmp2_; double tmp12_ = tmp8_ / 2.0; double tmp13_ = tmp9_ * tmp10_; double tmp14_ = tmp9_ * tmp2_; double tmp15_ = tmp9_ * tmp12_; D[0*3+0] = tmp13_; D[0*3+1] = tmp14_; D[0*3+2] = 0; D[1*3+0] = tmp14_; D[1*3+1] = tmp13_; D[1*3+2] = 0; D[2*3+0] = 0; D[2*3+1] = 0; D[2*3+2] = tmp15_; } /* */ } void ME::plane_stress(double E, double nu) { /* input E, nu; output D(3,3); D = E/(1-nu*nu) * [ 1, nu, 0; nu, 1, 0; 0, 0, (1-nu)/2 ]; */ /* */ { double tmp1_ = E; double tmp2_ = nu; double tmp4_ = tmp2_ * tmp2_; double tmp5_ = 1.0 - tmp4_; double tmp6_ = tmp1_ / tmp5_; double tmp8_ = 1.0 - tmp2_; double tmp10_ = tmp8_ / 2.0; double tmp11_ = tmp6_ * tmp2_; double tmp12_ = tmp6_ * tmp10_; D[0*3+0] = tmp6_; D[0*3+1] = tmp11_; D[0*3+2] = 0; D[1*3+0] = tmp11_; D[1*3+1] = tmp6_; D[1*3+2] = 0; D[2*3+0] = 0; D[2*3+1] = 0; D[2*3+2] = tmp12_; } /* */ } void ME::assign_ids(Mesh* mesh, int eltid) { for (int i = 0; i < 4; ++i) { int ni = mesh->ix(i,eltid); mesh->id(0,ni) = 1; mesh->id(1,ni) = 1; } } void ME::assemble_f(Mesh* mesh, int eltid) { Quad2d quad; Gauss4 xi(quad); get_quad(quad, mesh, eltid); vector K(4*4); for (xi.start(); !xi.done(); ++xi) { double eps[3] = {0, 0, 0}; for (int j = 0; j < 4; ++j) { const double* u = mesh->u(mesh->ix(j,eltid)); double Nj_x = xi.dN(j,0); double Nj_y = xi.dN(j,1); /* // Contribute strain at quadrature point input Nj_x, Nj_y, D(3,3); inout eps(3); input u(2); Bj = [Nj_x, 0; 0, Nj_y; Nj_y, Nj_x]; eps += Bj*u; */ /* */ { double tmp1_ = Nj_x; double tmp2_ = Nj_y; double tmp3_ = eps[0*3+0]; double tmp4_ = eps[0*3+1]; double tmp5_ = eps[0*3+2]; double tmp6_ = u[0*2+0]; double tmp7_ = u[0*2+1]; double tmp8_ = tmp1_ * tmp6_; double tmp9_ = tmp2_ * tmp7_; double tmp10_ = tmp2_ * tmp6_; double tmp11_ = tmp1_ * tmp7_; double tmp12_ = tmp10_ + tmp11_; double tmp13_ = tmp3_ + tmp8_; double tmp14_ = tmp4_ + tmp9_; double tmp15_ = tmp5_ + tmp12_; eps[0*3+0] = tmp13_; eps[0*3+1] = tmp14_; eps[0*3+2] = tmp15_; } /* */ } for (int i = 0; i < 4; ++i) { double* f = mesh->f(mesh->ix(i,eltid)); double Ni_x = xi.dN(i,0); double Ni_y = xi.dN(i,1); double w = xi.wt(); /* // Contribute B_i'*D*B(u) * w input Ni_x, Ni_y, D(3,3), w; input eps(3); inout f(2); Bi = [Ni_x, 0; 0, Ni_y; Ni_y, Ni_x]; f += Bi'*D*eps*w; */ /* */ { double tmp1_ = Ni_x; double tmp2_ = Ni_y; double tmp3_ = D[0*3+0]; double tmp4_ = D[0*3+1]; double tmp5_ = D[0*3+2]; double tmp6_ = D[1*3+0]; double tmp7_ = D[1*3+1]; double tmp8_ = D[1*3+2]; double tmp9_ = D[2*3+0]; double tmp10_ = D[2*3+1]; double tmp11_ = D[2*3+2]; double tmp12_ = w; double tmp13_ = eps[0*3+0]; double tmp14_ = eps[0*3+1]; double tmp15_ = eps[0*3+2]; double tmp16_ = f[0*2+0]; double tmp17_ = f[0*2+1]; double tmp18_ = tmp1_ * tmp3_; double tmp19_ = tmp2_ * tmp5_; double tmp20_ = tmp18_ + tmp19_; double tmp21_ = tmp2_ * tmp4_; double tmp22_ = tmp1_ * tmp5_; double tmp23_ = tmp21_ + tmp22_; double tmp24_ = tmp1_ * tmp6_; double tmp25_ = tmp2_ * tmp8_; double tmp26_ = tmp24_ + tmp25_; double tmp27_ = tmp2_ * tmp7_; double tmp28_ = tmp1_ * tmp8_; double tmp29_ = tmp27_ + tmp28_; double tmp30_ = tmp1_ * tmp9_; double tmp31_ = tmp2_ * tmp11_; double tmp32_ = tmp30_ + tmp31_; double tmp33_ = tmp2_ * tmp10_; double tmp34_ = tmp1_ * tmp11_; double tmp35_ = tmp33_ + tmp34_; double tmp36_ = tmp20_ * tmp13_; double tmp37_ = tmp26_ * tmp14_; double tmp38_ = tmp36_ + tmp37_; double tmp39_ = tmp32_ * tmp15_; double tmp40_ = tmp38_ + tmp39_; double tmp41_ = tmp23_ * tmp13_; double tmp42_ = tmp29_ * tmp14_; double tmp43_ = tmp41_ + tmp42_; double tmp44_ = tmp35_ * tmp15_; double tmp45_ = tmp43_ + tmp44_; double tmp46_ = tmp40_ * tmp12_; double tmp47_ = tmp45_ * tmp12_; double tmp48_ = tmp16_ + tmp46_; double tmp49_ = tmp17_ + tmp47_; f[0*2+0] = tmp48_; f[0*2+1] = tmp49_; } /* */ } } } void ME::assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler) { Quad2d quad; Gauss4 xi(quad); get_quad(quad, mesh, eltid); vector K(8*8); for (xi.start(); !xi.done(); ++xi) { double w = xi.wt(); for (int j = 0; j < 4; ++j) { double Nj_x = xi.dN(j,0); double Nj_y = xi.dN(j,1); for (int i = 0; i < 4; ++i) { double Ni_x = xi.dN(i,0); double Ni_y = xi.dN(i,1); double* Knodal = &(K[16*j +2*i+ 0]); /* // B-matrix based displacement formulation // Isotropic plane strain constitutive tensor input D(3,3), w; input Ni_x, Ni_y, Nj_x, Nj_y; inout Knodal[8](2,2); Bi = [Ni_x, 0; 0, Ni_y; Ni_y, Ni_x]; Bj = [Nj_x, 0; 0, Nj_y; Nj_y, Nj_x]; Knodal += Bi'*D*Bj * w; */ /* */ { double tmp1_ = D[0*3+0]; double tmp2_ = D[0*3+1]; double tmp3_ = D[0*3+2]; double tmp4_ = D[1*3+0]; double tmp5_ = D[1*3+1]; double tmp6_ = D[1*3+2]; double tmp7_ = D[2*3+0]; double tmp8_ = D[2*3+1]; double tmp9_ = D[2*3+2]; double tmp10_ = w; double tmp11_ = Ni_x; double tmp12_ = Ni_y; double tmp13_ = Nj_x; double tmp14_ = Nj_y; double tmp15_ = Knodal[0*8+0]; double tmp16_ = Knodal[0*8+1]; double tmp17_ = Knodal[1*8+0]; double tmp18_ = Knodal[1*8+1]; double tmp19_ = tmp11_ * tmp1_; double tmp20_ = tmp12_ * tmp3_; double tmp21_ = tmp19_ + tmp20_; double tmp22_ = tmp12_ * tmp2_; double tmp23_ = tmp11_ * tmp3_; double tmp24_ = tmp22_ + tmp23_; double tmp25_ = tmp11_ * tmp4_; double tmp26_ = tmp12_ * tmp6_; double tmp27_ = tmp25_ + tmp26_; double tmp28_ = tmp12_ * tmp5_; double tmp29_ = tmp11_ * tmp6_; double tmp30_ = tmp28_ + tmp29_; double tmp31_ = tmp11_ * tmp7_; double tmp32_ = tmp12_ * tmp9_; double tmp33_ = tmp31_ + tmp32_; double tmp34_ = tmp12_ * tmp8_; double tmp35_ = tmp11_ * tmp9_; double tmp36_ = tmp34_ + tmp35_; double tmp37_ = tmp21_ * tmp13_; double tmp38_ = tmp33_ * tmp14_; double tmp39_ = tmp37_ + tmp38_; double tmp40_ = tmp24_ * tmp13_; double tmp41_ = tmp36_ * tmp14_; double tmp42_ = tmp40_ + tmp41_; double tmp43_ = tmp27_ * tmp14_; double tmp44_ = tmp33_ * tmp13_; double tmp45_ = tmp43_ + tmp44_; double tmp46_ = tmp30_ * tmp14_; double tmp47_ = tmp36_ * tmp13_; double tmp48_ = tmp46_ + tmp47_; double tmp49_ = tmp39_ * tmp10_; double tmp50_ = tmp42_ * tmp10_; double tmp51_ = tmp45_ * tmp10_; double tmp52_ = tmp48_ * tmp10_; double tmp53_ = tmp15_ + tmp49_; double tmp54_ = tmp16_ + tmp50_; double tmp55_ = tmp17_ + tmp51_; double tmp56_ = tmp18_ + tmp52_; Knodal[0*8+0] = tmp53_; Knodal[0*8+1] = tmp54_; Knodal[1*8+0] = tmp55_; Knodal[1*8+1] = tmp56_; } /* */ } } } K_assembler->add_entry(id, id, &(K[0]), 8, 8); } void ME::get_quad(FEShapes& quad, Mesh* mesh, int eltid) { for (int i = 0; i < 4; ++i) { int n = mesh->ix(i,eltid); quad.set_node(i, mesh->x(n)); id[2*i+0] = mesh->id(0,n); id[2*i+1] = mesh->id(1,n); } } mwrap-1.1.1/example/fem/src/etype.h000066400000000000000000000010001430266125200171200ustar00rootroot00000000000000/* * etype.h * Element type interface definition. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef ETYPE_H #define ETYPE_H #include "assembler.h" class Mesh; class EType { public: virtual ~EType(); virtual void assign_ids(Mesh* mesh, int eltid) = 0; virtual void assemble_f(Mesh* mesh, int eltid) = 0; virtual void assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler) = 0; }; #endif /* ETYPE_H */ mwrap-1.1.1/example/fem/src/feintegrals.h000066400000000000000000000021101430266125200203000ustar00rootroot00000000000000/* * feintegrals.h * Interface for element quadrature rules. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef FEINTEGRALS_H #define FEINTEGRALS_H #include "feshapes.h" #include using std::vector; class VolumeQuadrature { public: VolumeQuadrature(FEShapes& quad, int ndim) : quad(quad), nshape1(quad.nshape()), xx1(2), N1(quad.nshape()), dN1(ndim*quad.nshape()) {} virtual void start() = 0; virtual bool done() = 0; virtual void operator++() = 0; virtual double wt() = 0; int nshape() { return nshape1; } double* xx() { return &(xx1[0]); } double* N() { return &(N1[0]); } double* dN() { return &(dN1[0]); } double xx(int i) { return xx1[i]; } double N(int i) { return N1[i]; } double dN(int i, int j) { return dN1[i+j*nshape1]; } protected: FEShapes& quad; int nshape1; vector xx1; vector N1; vector dN1; double J; }; #endif /* FEINTEGRALS_H */ mwrap-1.1.1/example/fem/src/feshapes.h000066400000000000000000000010621430266125200176000ustar00rootroot00000000000000/* * feshapes.h * Interface for element shape functions. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef FESHAPES_H #define FESHAPES_H class FEShapes { public: virtual ~FEShapes() {} virtual void set_node(int nodenum, const double* x) = 0; virtual void set_nodes(const double* x) = 0; virtual void eval(const double *XX, double* xx, double* N, double* dN, double& J) const = 0; virtual int nshape() const = 0; }; #endif /* FESHAPES_H */ mwrap-1.1.1/example/fem/src/gauss2by2.cc000066400000000000000000000007151430266125200177650ustar00rootroot00000000000000/* * gauss2by2.cc * Parent domain node locations and weights for quadrature on a * 2-by-2 Gauss grid over [-1,1]^2. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "gauss2by2.h" const double Gauss4::X[12] = { -0.577350269189626, -0.577350269189626, 1, 0.577350269189626, -0.577350269189626, 1, 0.577350269189626, 0.577350269189626, 1, -0.577350269189626, 0.577350269189626, 1, }; mwrap-1.1.1/example/fem/src/gauss2by2.h000066400000000000000000000013071430266125200176250ustar00rootroot00000000000000/* * gauss2by2.h * 2-by-2 Gauss grid quadrature over [-1,1]^2. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef GAUSS2BY2_H #define GAUSS2BY2_H #include "feshapes.h" #include "feintegrals.h" class Gauss4 : public VolumeQuadrature { public: Gauss4(FEShapes& quad) : VolumeQuadrature(quad, 2) { start(); } void start() { i = 0; eval(); } bool done() { return (i > 3); } void operator++() { if (++i <= 3) eval(); } double wt() { return X[3*i+2]*J; } private: static const double X[12]; int i; void eval() { quad.eval(X+3*i, xx(), N(), dN(), J); } }; #endif /* GAUSS2BY2_H */ mwrap-1.1.1/example/fem/src/mesh.cc000066400000000000000000000042041430266125200170750ustar00rootroot00000000000000/* * mesh.cc * Finite element mesh implementation. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "mesh.h" #define ME Mesh EType::~EType() { } ME::~ME() { for (vector::iterator i = materials_owned.begin(); i != materials_owned.end(); ++i) { delete(*i); } } int ME::add_node(double* x) { int id = numnp(); for (int i = 0; i < ndm_; ++i) X.push_back(x[i]); return id; } int ME::add_element(EType* etype, int* nodes, int nen) { int id = numelt(); int i = 0; for (; i < nen && i < maxnen_; ++i) IX.push_back(nodes[i]); for (; i < maxnen_; ++i) IX.push_back(-1); elements.push_back(etype); return id; } void ME::add_material(EType* material) { materials_owned.push_back(material); } void ME::set_ur(const double* ur) { for (int i = 0; i < ID.size(); ++i) { if (ID[i] >= 0) U[i] = ur[ID[i]]; if (BC[i]) U[i] = BV[i]; } } void ME::get_ur(double* ur) { for (int i = 0; i < ID.size(); ++i) if (ID[i] >= 0) ur[ID[i]] = U[i]; } void ME::get_fr(double* fr) { for (int i = 0; i < ID.size(); ++i) { if (ID[i] >= 0) fr[ID[i]] = R[i]; if (!BC[i]) fr[ID[i]] -= BV[i]; } } int ME::initialize() { ID.resize(maxndf_ * numnp()); R.resize (maxndf_ * numnp()); U.resize (maxndf_ * numnp()); BC.resize(maxndf_ * numnp()); BV.resize(maxndf_ * numnp()); return assign_ids(); } int ME::assign_ids() { numid_ = 0; int n = numelt(); for (int i = 0; i < ID.size(); ++i) ID[i] = 0; for (int i = 0; i < n; ++i) if (elements[i]) elements[i]->assign_ids(this, i); for (int i = 0; i < ID.size(); ++i) ID[i] = ( (ID[i] && !BC[i]) ? numid_++ : -1 ); return numid_; } void ME::assemble_F() { int n = numelt(); for (int i = 0; i < n; ++i) if (elements[i]) elements[i]->assemble_f(this, i); } void ME::assemble_K(MatrixAssembler* K_assembler) { int n = numelt(); for (int i = 0; i < n; ++i) if (elements[i]) elements[i]->assemble_K(this, i, K_assembler); } mwrap-1.1.1/example/fem/src/mesh.h000066400000000000000000000065341430266125200167470ustar00rootroot00000000000000/* * mesh.h * Finite element mesh implementation. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef MESH_H #define MESH_H #include "assembler.h" #include "etype.h" #include using std::vector; class Mesh { public: Mesh(int ndm, int maxndf, int maxnen) : ndm_(ndm), maxndf_(maxndf), maxnen_(maxnen), numid_(0) {} ~Mesh(); int ndm() const { return ndm_; } int maxndf() const { return maxndf_; } int maxnen() const { return maxnen_; } int numelt() const { return elements.size(); } int numnp() const { return X.size() / ndm_; } int numid() const { return numid_; } double* x () { return &(X[0]); } int* ix() { return &(IX[0]); } int* id() { return &(ID[0]); } double* u () { return &(U[0]); } double* f () { return &(R[0]); } char* bc() { return &(BC[0]); } double* bv() { return &(BV[0]); } const double* x (int j) const { return &(X [j*ndm_]); } const int* ix(int j) const { return &(IX[j*maxnen_]); } const int* id(int j) const { return &(ID[j*maxndf_]); } const double* u (int j) const { return &(U [j*maxndf_]); } const double* f (int j) const { return &(R [j*maxndf_]); } double* f (int j) { return &(R [j*maxndf_]); } const char* bc(int j) const { return &(BC[j*maxndf_]); } const double* bv(int j) const { return &(BV[j*maxndf_]); } double x (int i, int j) const { return X [i+j*ndm_]; } int ix(int i, int j) const { return IX[i+j*maxnen_]; } int id(int i, int j) const { return ID[i+j*maxndf_]; } int& id(int i, int j) { return ID[i+j*maxndf_]; } double u (int i, int j) const { return U [i+j*maxndf_]; } double f (int i, int j) const { return R [i+j*maxndf_]; } double& f (int i, int j) { return R [i+j*maxndf_]; } char bc(int i, int j) const { return BC[i+j*maxndf_]; } char& bc(int i, int j) { return BC[i+j*maxndf_]; } double bv(int i, int j) const { return BV[i+j*maxndf_]; } double& bv(int i, int j) { return BV[i+j*maxndf_]; } void set_ur(const double* ur); void get_ur(double* ur); void get_fr(double* ur); int initialize(); int assign_ids(); void assemble_F(); void assemble_K(MatrixAssembler* K_assembler); int add_node(double* x); int add_element(EType* etype, int* nodes, int numnp); void add_material(EType* material); private: Mesh(const Mesh&); Mesh& operator=(const Mesh&); int ndm_; // Number of spatial dimensions int maxndf_; // Maximum degrees of freedom per node int maxnen_; // Maximum number of nodes per element int numid_; // Number of active degrees of freedom vector X; // Coordinate array ( ndm * numnp ) vector IX; // Element connectivity ( maxnen * numelt ) vector ID; // Identifier assignment ( maxndf * numnp ) vector R; // Full residual vector ( maxndf * numnp ) vector U; // Full solution ( maxndf * numnp ) vector BC; // Flag Dirichlet BCs ( maxndf * numnp ) vector BV; // Boundary values ( maxndf * numnp ) vector elements; // Material assignment (numelt) vector materials_owned; }; #endif /* MESH_H */ mwrap-1.1.1/example/fem/src/quad2d.cc000066400000000000000000000025531430266125200173260ustar00rootroot00000000000000/* * quad2d.h * Implementation for four-node quad element shapes. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "quad2d.h" #define ME Quad2d ME::~ME() { } void ME::set_node(int nodenum, const double* x) { nodex[2*nodenum+0] = x[0]; nodex[2*nodenum+1] = x[1]; } void ME::set_nodes(const double* x) { for (int i = 0; i < 8; ++i) nodex[i] = x[i]; } void ME::eval(const double *XX, double* xx, double* N, double* dN, double& J) const { double X = XX[0]; double Y = XX[1]; double FF[4]; /* // Evaluate element functions input X, Y; input nodex(2,4); output N(4); output dN(4,2); output xx(2); output FF(2,2); N1x = (1-X)/2; N1y = (1-Y)/2; N2x = (1+X)/2; N2y = (1+Y)/2; N = [ N1x*N1y; N2x*N1y; N2x*N2y; N1x*N2y]; dN = [ -N1y, N1y, N2y, -N2y; -N1x, -N2x, N2x, N1x ]'/2; xx = nodex*N; FF = nodex*dN; */ remap_gradients(FF, dN, J); } void ME::remap_gradients(double* FF, double* dN, double& J) const { J = (FF[0]*FF[3]-FF[1]*FF[2]); double invF[4] = { FF[3]/J, -FF[1]/J, -FF[2]/J, FF[0]/J }; /* // Remap gradients inout dN(4,2); input invF(2,2); dN = dN*invF; */ } mwrap-1.1.1/example/fem/src/quad2d.h000066400000000000000000000013011430266125200171560ustar00rootroot00000000000000/* * quad2d.h * Interface for four-node quad element shapes. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef QUAD2D_H #define QUAD2D_H #include "feshapes.h" class Quad2d : public FEShapes { public: Quad2d() {} Quad2d(const double* x) { set_nodes(x); } virtual ~Quad2d(); void set_node(int nodenum, const double* x); void set_nodes(const double* x); void eval(const double *XX, double* xx, double* N, double* dN, double& J) const; int nshape() const { return 4; } private: double nodex[2*4]; void remap_gradients(double* FF, double* dN, double& J) const; }; #endif /* QUAD2D_H */ mwrap-1.1.1/example/fem/src/quad2d1.cc000066400000000000000000000136061430266125200174100ustar00rootroot00000000000000/* * quad2d.h * Implementation for four-node quad element shapes. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "quad2d.h" #define ME Quad2d ME::~ME() { } void ME::set_node(int nodenum, const double* x) { nodex[2*nodenum+0] = x[0]; nodex[2*nodenum+1] = x[1]; } void ME::set_nodes(const double* x) { for (int i = 0; i < 8; ++i) nodex[i] = x[i]; } void ME::eval(const double *XX, double* xx, double* N, double* dN, double& J) const { double X = XX[0]; double Y = XX[1]; double FF[4]; /* // Evaluate element functions input X, Y; input nodex(2,4); output N(4); output dN(4,2); output xx(2); output FF(2,2); N1x = (1-X)/2; N1y = (1-Y)/2; N2x = (1+X)/2; N2y = (1+Y)/2; N = [ N1x*N1y; N2x*N1y; N2x*N2y; N1x*N2y]; dN = [ -N1y, N1y, N2y, -N2y; -N1x, -N2x, N2x, N1x ]'/2; xx = nodex*N; FF = nodex*dN; */ /* */ { double tmp1_ = X; double tmp2_ = Y; double tmp3_ = nodex[0*2+0]; double tmp4_ = nodex[0*2+1]; double tmp5_ = nodex[1*2+0]; double tmp6_ = nodex[1*2+1]; double tmp7_ = nodex[2*2+0]; double tmp8_ = nodex[2*2+1]; double tmp9_ = nodex[3*2+0]; double tmp10_ = nodex[3*2+1]; double tmp12_ = 1.0 - tmp1_; double tmp14_ = tmp12_ / 2.0; double tmp15_ = 1.0 - tmp2_; double tmp16_ = tmp15_ / 2.0; double tmp17_ = 1.0 + tmp1_; double tmp18_ = tmp17_ / 2.0; double tmp19_ = 1.0 + tmp2_; double tmp20_ = tmp19_ / 2.0; double tmp21_ = tmp14_ * tmp16_; double tmp22_ = tmp18_ * tmp16_; double tmp23_ = tmp18_ * tmp20_; double tmp24_ = tmp14_ * tmp20_; double tmp25_ = -tmp16_; double tmp26_ = -tmp20_; double tmp27_ = -tmp14_; double tmp28_ = -tmp18_; double tmp29_ = tmp25_ / 2.0; double tmp30_ = tmp16_ / 2.0; double tmp31_ = tmp20_ / 2.0; double tmp32_ = tmp26_ / 2.0; double tmp33_ = tmp27_ / 2.0; double tmp34_ = tmp28_ / 2.0; double tmp35_ = tmp18_ / 2.0; double tmp36_ = tmp14_ / 2.0; double tmp37_ = tmp3_ * tmp21_; double tmp38_ = tmp5_ * tmp22_; double tmp39_ = tmp37_ + tmp38_; double tmp40_ = tmp7_ * tmp23_; double tmp41_ = tmp39_ + tmp40_; double tmp42_ = tmp9_ * tmp24_; double tmp43_ = tmp41_ + tmp42_; double tmp44_ = tmp4_ * tmp21_; double tmp45_ = tmp6_ * tmp22_; double tmp46_ = tmp44_ + tmp45_; double tmp47_ = tmp8_ * tmp23_; double tmp48_ = tmp46_ + tmp47_; double tmp49_ = tmp10_ * tmp24_; double tmp50_ = tmp48_ + tmp49_; double tmp51_ = tmp3_ * tmp29_; double tmp52_ = tmp5_ * tmp30_; double tmp53_ = tmp51_ + tmp52_; double tmp54_ = tmp7_ * tmp31_; double tmp55_ = tmp53_ + tmp54_; double tmp56_ = tmp9_ * tmp32_; double tmp57_ = tmp55_ + tmp56_; double tmp58_ = tmp4_ * tmp29_; double tmp59_ = tmp6_ * tmp30_; double tmp60_ = tmp58_ + tmp59_; double tmp61_ = tmp8_ * tmp31_; double tmp62_ = tmp60_ + tmp61_; double tmp63_ = tmp10_ * tmp32_; double tmp64_ = tmp62_ + tmp63_; double tmp65_ = tmp3_ * tmp33_; double tmp66_ = tmp5_ * tmp34_; double tmp67_ = tmp65_ + tmp66_; double tmp68_ = tmp7_ * tmp35_; double tmp69_ = tmp67_ + tmp68_; double tmp70_ = tmp9_ * tmp36_; double tmp71_ = tmp69_ + tmp70_; double tmp72_ = tmp4_ * tmp33_; double tmp73_ = tmp6_ * tmp34_; double tmp74_ = tmp72_ + tmp73_; double tmp75_ = tmp8_ * tmp35_; double tmp76_ = tmp74_ + tmp75_; double tmp77_ = tmp10_ * tmp36_; double tmp78_ = tmp76_ + tmp77_; N[0*4+0] = tmp21_; N[0*4+1] = tmp22_; N[0*4+2] = tmp23_; N[0*4+3] = tmp24_; dN[0*4+0] = tmp29_; dN[0*4+1] = tmp30_; dN[0*4+2] = tmp31_; dN[0*4+3] = tmp32_; dN[1*4+0] = tmp33_; dN[1*4+1] = tmp34_; dN[1*4+2] = tmp35_; dN[1*4+3] = tmp36_; xx[0*2+0] = tmp43_; xx[0*2+1] = tmp50_; FF[0*2+0] = tmp57_; FF[0*2+1] = tmp64_; FF[1*2+0] = tmp71_; FF[1*2+1] = tmp78_; } /* */ remap_gradients(FF, dN, J); } void ME::remap_gradients(double* FF, double* dN, double& J) const { J = (FF[0]*FF[3]-FF[1]*FF[2]); double invF[4] = { FF[3]/J, -FF[1]/J, -FF[2]/J, FF[0]/J }; /* // Remap gradients inout dN(4,2); input invF(2,2); dN = dN*invF; */ /* */ { double tmp1_ = dN[0*4+0]; double tmp2_ = dN[0*4+1]; double tmp3_ = dN[0*4+2]; double tmp4_ = dN[0*4+3]; double tmp5_ = dN[1*4+0]; double tmp6_ = dN[1*4+1]; double tmp7_ = dN[1*4+2]; double tmp8_ = dN[1*4+3]; double tmp9_ = invF[0*2+0]; double tmp10_ = invF[0*2+1]; double tmp11_ = invF[1*2+0]; double tmp12_ = invF[1*2+1]; double tmp13_ = tmp1_ * tmp9_; double tmp14_ = tmp5_ * tmp10_; double tmp15_ = tmp13_ + tmp14_; double tmp16_ = tmp2_ * tmp9_; double tmp17_ = tmp6_ * tmp10_; double tmp18_ = tmp16_ + tmp17_; double tmp19_ = tmp3_ * tmp9_; double tmp20_ = tmp7_ * tmp10_; double tmp21_ = tmp19_ + tmp20_; double tmp22_ = tmp4_ * tmp9_; double tmp23_ = tmp8_ * tmp10_; double tmp24_ = tmp22_ + tmp23_; double tmp25_ = tmp1_ * tmp11_; double tmp26_ = tmp5_ * tmp12_; double tmp27_ = tmp25_ + tmp26_; double tmp28_ = tmp2_ * tmp11_; double tmp29_ = tmp6_ * tmp12_; double tmp30_ = tmp28_ + tmp29_; double tmp31_ = tmp3_ * tmp11_; double tmp32_ = tmp7_ * tmp12_; double tmp33_ = tmp31_ + tmp32_; double tmp34_ = tmp4_ * tmp11_; double tmp35_ = tmp8_ * tmp12_; double tmp36_ = tmp34_ + tmp35_; dN[0*4+0] = tmp15_; dN[0*4+1] = tmp18_; dN[0*4+2] = tmp21_; dN[0*4+3] = tmp24_; dN[1*4+0] = tmp27_; dN[1*4+1] = tmp30_; dN[1*4+2] = tmp33_; dN[1*4+3] = tmp36_; } /* */ } mwrap-1.1.1/example/fem/src/scalar1d.cc000066400000000000000000000020501430266125200176300ustar00rootroot00000000000000/* * scalar1d.cc * Element type for 1D Laplacian. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "scalar1d.h" #define ME Scalar1D void ME::assign_ids(Mesh* mesh, int eltid) { int n1 = mesh->ix(0,eltid); int n2 = mesh->ix(1,eltid); mesh->id(0,n1) = 1; mesh->id(0,n2) = 1; } void ME::assemble_f(Mesh* mesh, int eltid) { int n1 = mesh->ix(0,eltid); int n2 = mesh->ix(1,eltid); double L = mesh->x(0,n2) - mesh->x(0,n1); double kappa = k/L; double udiff = mesh->u(0,n2) - mesh->u(0,n1); mesh->f(0,n1) -= kappa*udiff; mesh->f(0,n2) += kappa*udiff; } void ME::assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler) { int n1 = mesh->ix(0,eltid); int n2 = mesh->ix(1,eltid); double L = mesh->x(0,n2) - mesh->x(0,n1); double kappa = k/L; int i[2] = {mesh->id(0,n1), mesh->id(0,n2)}; double K_elt[4] = { kappa, -kappa, -kappa, kappa }; K_assembler->add_entry(i, i, K_elt, 2, 2); } mwrap-1.1.1/example/fem/src/scalar1d.h000066400000000000000000000010221430266125200174700ustar00rootroot00000000000000/* * scalar1d.h * Element type for 1D Laplacian. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef SCALAR1D_H #define SCALAR1D_H #include "etype.h" #include "mesh.h" class Scalar1D : public EType { public: Scalar1D(double k) : k(k) {} void assign_ids(Mesh* mesh, int eltid); void assemble_f(Mesh* mesh, int eltid); void assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler); private: double k; }; #endif /* SCALAR1D_H */ mwrap-1.1.1/example/fem/src/scalar2d.cc000066400000000000000000000033531430266125200176400ustar00rootroot00000000000000/* * scalar2d.cc * Element type for 2D Laplacian (4 node quad only). * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "etype.h" #include "mesh.h" #include "scalar2d.h" #include "quad2d.h" #include "gauss2by2.h" #define ME Scalar2D void ME::assign_ids(Mesh* mesh, int eltid) { for (int i = 0; i < 4; ++i) mesh->id(0, mesh->ix(i,eltid)) = 1; } void ME::assemble_f(Mesh* mesh, int eltid) { Quad2d quad; Gauss4 xi(quad); get_quad(quad, mesh, eltid); vector K(4*4); for (xi.start(); !xi.done(); ++xi) { // Compute grad u at the quadrature point double dudx[2] = {0, 0}; for (int j = 0; j < 4; ++j) { double uj = mesh->u(0,mesh->ix(j,eltid)); dudx[0] += xi.dN(j,0) * uj; dudx[1] += xi.dN(j,1) * uj; } // Contribute k * dot(grad N_i, grad u) * wt for (int i = 0; i < 4; ++i) mesh->f(0,mesh->ix(i,eltid)) += k * (xi.dN(i,0) * dudx[0] + xi.dN(i,1) * dudx[1]) * xi.wt(); } } void ME::assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler) { Quad2d quad; Gauss4 xi(quad); get_quad(quad, mesh, eltid); vector K(4*4); for (xi.start(); !xi.done(); ++xi) for (int j = 0; j < 4; ++j) for (int i = 0; i < 4; ++i) K[4*j+i] += k * (xi.dN(i,0) * xi.dN(j,0) + xi.dN(i,1) * xi.dN(j,1)) * xi.wt(); K_assembler->add_entry(id, id, &(K[0]), 4, 4); } void ME::get_quad(FEShapes& quad, Mesh* mesh, int eltid) { for (int i = 0; i < 4; ++i) { int n = mesh->ix(i,eltid); quad.set_node(i, mesh->x(n)); id[i] = mesh->id(0,n); } } mwrap-1.1.1/example/fem/src/scalar2d.h000066400000000000000000000011621430266125200174760ustar00rootroot00000000000000/* * scalar2d.h * Element type for 2D Laplacian. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef SCALAR2D_H #define SCALAR2D_H #include "etype.h" #include "mesh.h" #include "feshapes.h" class Scalar2D : public EType { public: Scalar2D(double k) : k(k) {} void assign_ids(Mesh* mesh, int eltid); void assemble_f(Mesh* mesh, int eltid); void assemble_K(Mesh* mesh, int eltid, MatrixAssembler* K_assembler); private: double k; int id[4]; void get_quad(FEShapes& quad, Mesh* mesh, int eltid); }; #endif /* SCALAR2D_H */ mwrap-1.1.1/example/fem/test_assembler.m000066400000000000000000000022251430266125200202360ustar00rootroot00000000000000% test_assembler.m % Test MWrap interface to CSC matrix assembler. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions init; N = 1000; aobj = Assembler_create(N,N); try fprintf('\nRunning initial assembly loop\n'); tic; for j = 1:N idx = [j, j+1]; Ke = [1, -1; -1, 1]; Assembler_add(aobj, idx, idx, Ke); end toc; fprintf('Nonzeros in assembler before compression and form\n'); Assembler_stats(aobj); K = Assembler_get(aobj); fprintf('Nonzeros in assembler after compression and form\n'); Assembler_stats(aobj); fprintf('\nRe-running assembly loop\n'); Assembler_clear(aobj); tic; for j = 1:N idx = [j, j+1]; Ke = [1, -1; -1, 1]; Assembler_add(aobj, idx, idx, Ke); end toc; fprintf('Nonzeros in assembler before compression and form\n'); Assembler_stats(aobj); K = Assembler_get(aobj); fprintf('Nonzeros in assembler after compression and form\n'); Assembler_stats(aobj); fprintf('\nComparing the result matrices\n'); K2 = Assembler_get(aobj); fprintf('|K2-K1| = %g\n\n', norm(K-K2,1)); catch fprintf('Caught %s\n', lasterr); end Assembler_delete(aobj); mwrap-1.1.1/example/fem/test_patch.m000066400000000000000000000031441430266125200173610ustar00rootroot00000000000000% test_mesh3.m % Test MWrap interface to mesh data structure. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions init; mobj = Mesh_create(2, 2, 4); try fprintf('-- Four element elastic patch test --\n'); % Nodes: % 1 2 3 4 5 6 7 8 9 x = [ 0.0, 4.0, 10.0, 0.0, 5.5, 10.0, 0.0, 4.2, 10.0; 0.0, 0.0, 0.0, 4.5, 5.5, 5.0, 10.0, 10.0, 10.0]; % Boundary codes and values bc =[ 1, 0, 0, 1, 0, 0, 1, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0]; bv =[ 0, 0, 2.5, 0, 0, 5.0, 0, 0, 2.5, 0, 0, 0, 0, 0, 0, 0, 0, 0]; % Elements: % 1 2 3 4 ix = [ 1, 2, 4, 5 ; 2, 3, 5, 6 ; 5, 6, 8, 9 ; 4, 5, 7, 8 ]; % Set up problem mesh material = Mesh_add_elastic2d(mobj, 1000.0, 0.25, 'plane strain'); Mesh_load(mobj, material, x, ix); Mesh_initialize(mobj); % Set boundary conditions Mesh_set_bc(mobj, bc); Mesh_set_bv(mobj, bv); Mesh_assign_ids(mobj); % Assemble stiffness and force K = Mesh_assemble_K(mobj); F = Mesh_assemble_F(mobj); % Solve for the reduced displacement u = -K\F; % Patch test should recover linear fields -- check that it does uu = Mesh_u(mobj); resid = uu - (uu/x)*x; fprintf('Patch test residual: %g\n', norm(resid)); % Assemble residual and make sure it's zero Mesh_set_ur(mobj, u); RR = Mesh_assemble_F(mobj); fprintf('Reported residual force: %g\n', norm(RR)); catch fprintf('Error: %s\n', lasterr); end Mesh_delete(mobj); mwrap-1.1.1/example/fem/test_simple.m000066400000000000000000000017471430266125200175620ustar00rootroot00000000000000% test_mesh.m % Test MWrap interface to mesh data structure. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions init; mobj = Mesh_create(1, 1, 2); try % -- Set up a simple mesh i1 = Mesh_add_node(mobj, 0); i2 = Mesh_add_node(mobj, 1); i3 = Mesh_add_node(mobj, 2); i4 = Mesh_add_node(mobj, 3); s1 = Mesh_add_scalar1d(mobj, 1); e1 = Mesh_add_element(mobj, s1, [i1, i2]); e2 = Mesh_add_element(mobj, s1, [i2, i3]); e3 = Mesh_add_element(mobj, s1, [i3, i4]); Mesh_initialize(mobj); % -- Assign Dirichlet BC to first dof at node 1 Mesh_set_bc(mobj, 1, 1, 1); fprintf('-- Mesh nodes and connectivities --\n'); x = Mesh_x(mobj) ix = Mesh_ix(mobj) fprintf('-- Mesh dof assignments --\n'); numid = Mesh_initialize(mobj) id = Mesh_id(mobj) fprintf('-- Assembled stiffness (standard three-point stencil) --\n'); K = Mesh_assemble_K(mobj); K = full(K) catch fprintf('Error: %s\n', lasterr); end Mesh_delete(mobj); mwrap-1.1.1/example/foobar/000077500000000000000000000000001430266125200155445ustar00rootroot00000000000000mwrap-1.1.1/example/foobar/Makefile000066400000000000000000000002761430266125200172110ustar00rootroot00000000000000include ../../make.inc MW=../../mwrap all: $(MW) -mex fbmex -m foobar.m foobar.mw $(MW) -mex fbmex -c fbmex.c foobar.mw $(MEX) fbmex.c clean: rm -f foobar.m fbmex.c fbmex.mex* *.o* *~ mwrap-1.1.1/example/foobar/foobar.mw000066400000000000000000000002461430266125200173630ustar00rootroot00000000000000$ #include function foobar; s1 = 'foo'; s2 = 'bar'; # strncat(inout cstring[128] s1, cstring s2, int 127); fprintf('Should be foobar: %s\n', s1); mwrap-1.1.1/example/zlib/000077500000000000000000000000001430266125200152345ustar00rootroot00000000000000mwrap-1.1.1/example/zlib/Makefile000066400000000000000000000003051430266125200166720ustar00rootroot00000000000000# See www.zlib.net include ../../make.inc MW=../../mwrap gzmex: $(MW) -mex gzmex -mb gzfile.mw $(MW) -mex gzmex -c gzmex.c gzfile.mw $(MEX) gzmex.c -lz clean: rm -f gz*.m gzmex.* *.o* eye.gz mwrap-1.1.1/example/zlib/README000066400000000000000000000003111430266125200161070ustar00rootroot00000000000000This example illustrates bindings for the Zlib compression library (http://www.zlib.net/). The test illustrates how these bindings can be used to read and write MATLAB matrices in compressed storage. mwrap-1.1.1/example/zlib/gzfile.mw000066400000000000000000000026251430266125200170660ustar00rootroot00000000000000% gzfile.mw % MWrap wrapper to the ZLib compression library. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions $#include // ---- @function [gzf] = gzopen(path, mode) % [gzf] = gzopen(path, mode) % % Open a zlib output file. # void* gzf = gzopen(cstring path, cstring mode); // ---- @function gzclose(gzf) % gzclose(gzf) % % Close a zlib output file. # gzclose(void* gzf); // ---- @function [A] = gzread(gzf) % [A] = gzread(gzf) % % Read a matrix from a zlib file. # int isize = sizeof(int 0); # int dsize = sizeof(double 0); nbytes = 2*isize; # gzread(void* gzf, output int[2] dims, int nbytes); m = dims(1); n = dims(2); nbytes = m*n*dsize; # gzread(void* gzf, output double[m,n] A, int nbytes); % gzwrite(gzf, A) % % Write a matrix to a zlib file. // ---- @function gzwrite(gzf, A) % [A] = gzwrite(gzf, A) % % Write a matrix from a zlib file. # int isize = sizeof(int 0); # int dsize = sizeof(double 0); nbytes = 2*isize; [m,n] = size(A); dims = [m,n]; # gzwrite(void* gzf, int[2] dims, int nbytes); m = dims(1); n = dims(2); nbytes = m*n*dsize; # gzwrite(void* gzf, double[m,n] A, int nbytes); // ---- @function gzsave(path, A) % gzsave(path, A) % % Save a matrix to a zlib file. gzf = gzopen(path, 'w+'); gzwrite(gzf, A) // ---- @function [A] = gzload(path) % [A] = gzload(path) % % Read a matrix from a zlib file. gzf = gzopen(path, 'r'); A = gzread(gzf); mwrap-1.1.1/example/zlib/testgz.m000066400000000000000000000006511430266125200167340ustar00rootroot00000000000000% testgz.m % Test/demo a MWrap wrapper to the ZLib compression library. % % Copyright (c) 2007 David Bindel % See the file COPYING for copying permissions A = eye(100); fprintf('Writing identity to eye.gz\n'); fp = gzopen('eye.gz', 'w'); gzwrite(fp, A); gzclose(fp); fprintf('Reading identity back from eye.gz\n'); fp = gzopen('eye.gz', 'r'); B = gzread(fp); gzclose(fp); fprintf('Difference is = %g\n', norm(A-B,1)); mwrap-1.1.1/make.inc000066400000000000000000000010761430266125200142550ustar00rootroot00000000000000# === Compilers === # (You don't need flex and bison unless you're planning to modify the # grammar -- the default installation comes with the relevant files # already in place.) # Uncomment this line for new-style classdef support OOFLAG=-DR2008OO # Uncomment this line for C99 complex support TESTC99COMPLEX=test_c99_complex CC := $(if $(CC),$(CC),gcc) CXX := $(if $(CXX),$(CXX),g++) MEX= mex $(OOFLAG) # Use the following for 64-bit MEX # MEX= mex -largeArrayDims $(OOFLAG) # Use the following for GNU Octave. MEX= mkoctfile --mex FLEX= flex BISON= bison mwrap-1.1.1/mwrap.pdf000066400000000000000000006021461430266125200144730ustar00rootroot00000000000000%PDF-1.5 %ÐÔÅØ 3 0 obj << /Length 1770 /Filter /FlateDecode >> stream xÚ]Ó8ð_ N›Š‰8pwìOì'ÙÄÝF×&U’^Ù3žqšf³ÀKcÇóý徺~ôìM$=Š$QÚ»^{J&BEÚKt&²$ö®+ï³ÿáSWìW_¯ßv8ÅÎ!µöBBû«7Ý*ˆBå¿=Ô•Á ^+fÊ T,ò0!Ä¿Wiæ›®¯Û†ð¥L^y2Qœ($ϲ‘q®èÄU7•Ù\¨$©È2Mhï!Äô¿©¯B¥˜IæÉT(©cdÈ\ •Æ^ Õé¾\R*í¿kV‘ô‡®"Ò¯å€BéI)r­­¬!ðqÝý©ÉÔ/ÎE.g²ºG¤~a ‘ùu³QÓ­‹ÒÐÑ­iLW l«ÔïïúÁìFt 6†ý¾îê€íš¾?½eü· íè»+du1Á¢±Êý7«Lù]ˤ æfÚ5ò'É€›â˜ýYnw†%¯VÊBÿÃK¤výçËW¸—~_võ~ ³/¡Œ·¦¿\2£LaeÎ>ß3£Î¥C;ÖÛ-ÑfkâZ°0¯ÿáS89¢œþÜph ¹ZIßôuG*HÿêÙÕÓ§¤´RRè4?×z}hJv‹Œý²ØnÑ™2gVC#H6î×Àáì[‚6CKߢ,Mï`›b ¢sÑÁºè7Êkë|@®ÌPÔ[¾i½r/•ùÿá-Ó uskU YWË fE‡ÅºYm,Àæ¤ÇR›UÅPÐY?t‡ýDy|"a%@šÛ-Z8YösFÆÔÀË@lï-vÛÝã›[sy&¹‹½Žó|SW•i(××ƥ̀ÅŠ“XŽ8¡õ̵‡]& qÔÞS*öYÇö_ÞÖÿZ‹Ón¸§là›ÇzØ0˜47e 6»#غí U)¯`k¾ F5”¦-d?F,í(R¥2Hþ†HQü&‰ˆçáë6Òä}øÚˆÇ¨JU[,¢ÈHÿ[±Ûo :9ÊØ¬peÝ¢w±kT’%*ƨ{¶Â"*d©n°ã˜Ï'ÑШ+­¯È3qxæl0ÑXX!,ˆ·%u1›Ÿ/mÿŠÃŒpŸ¬-µÿ¸nÊ-¦4ªŠ€_+˜Al~_ŠÔS½ÐX Úö¦è^XD©DBRÐs]Ÿë%ÑüÐ/ÿâÅÙ^#Õ"çøcÂCË€Ð`œ/¡ë¦= tP’ôŸ¥Ê¾­^^ž1T1´n‚H•-¹(Þz7‡5òºø¸iÛŠîܰÍÈÏ øKÿEFqsÁ z9’½çÄÑfè—œxA%´Õ O¹,ä868ñ§%ÀX°*Â,Ûm^Ô=AlWͱ«ÚØ…;”éIœp½…sH@^q²ÝÖMCiwlZ/ÄR”Á¸îÉ’v2„@çªÁ`¦.”.¥E"ÓöJx)ÒdVñ©^¤!«©RÉ !Œ !÷@{Øö®0óÅ1Ñ/±a*ªéD‘É8‚òž…ðôA E©ÈãQýÇK:åìè0Î*K^_ª$V¨öL8¹\F‚(NEÍRìábCeÍ"'ˆKq;Q)Š•%N XYQ!ý üÛR€0,#PCz·£’?¤˜ÍSÜŽêïí@À­ƒA-}o¦@耭€s$ý™²LDlöĺuw{pöy•‡ìmÛß{7AÍýAqÜ`w/ñꆰöEWì ̸½#nÕ (­€÷dhæ‡`8TBºød …гVL—”ØË“hã|ª~fͳmßqRJÃìÎ+Hn\+7C<§¼ „«©p´3:Ú-ÕöHØ Á3Ÿ¡œíë-6ìŠ|,ÓHdrædš90F­»q1™ØòB†Zh¨³¬æÎ|[²…ŠÄ˜”4ã@°Sr”!ÔÐ1s‚{|¡” 4½e¢1ny\!‘‹®ÙÁAcNaón}RL r†³èpiuJ¦µž;A¿d ˜¦¢ÓŽ˜Ø— ¢µˆ’±B£1lëg*WìÅÜ…‹m–(ÓéUc{[CÐùcŽXø¡U¢ì|&õ¢Ð,G¡iRG¶\3¢LèxÖM¬#pÌæwÞ’ÕêÈþ"H<EšÞóá4T'³<5ÞEÏÀ›=„ç©> vøÈ¥#@–4wÜŒËân7F„ÛáhâÝùló3„Ë TÀF†çëïR=QBÁìµN@<™¾´áÌe ¸o×4åðÿ!Gó ûSC‹îÀ/(Î{ebÿ:‹¢ÅªŒŒÏk±po³ôô6›þY`å”ý`'q/‚dËñ? X¤2wÎÀÉ£××þÂvÃ× endstream endobj 13 0 obj << /Length 2357 /Filter /FlateDecode >> stream xÚ­kÛ6òûþ ;>%ªŠk‚öÐâzÅ!{`“²$¯u‘%Ÿ$ß&ÿþf8Ô˕כ"X`E‡ÃyÏ~s÷ú'%6B°Ä¹¹ßo¤•ÌÚM¬ |ìæ>ß<¿þ«MOÛ÷¿Üýx÷ß;±áð'6±4Á”1›ìx÷ðor€ÿ²áL%vóä°ŽYøV›ww¿{ƒçi>?Ïj¦¸ÞÄ­é$AåJ)ë®/ÒœNw¦ƒ/ÙÂñÐ|,ëÇÕÓ¹fvRî•ÄeÚD()¶|UZëèÎw@À´£q(hyßTU³u*Ÿô öøí3¥LKŸã9K.:\t¸\ÛœûÓ¹‡é‡qi¾ÀŽ#<»ØÀ²iË¯ŠX"ÄÒÈaUvýÚü‚…YÚg‡–v:!I0kTž\ÍN§´âAe!/»D¯Á¹¤9clÍ¡NÐI–…ãéP´ƒY©“u´Tä{)øzFb17c¾½’¤e‘swG¥ÈÊ÷\h 3aO6‡tP§Ç‚@˜œfK•‡³±)jjPà.g¹ßí‹Í}ÔÕ¥¡gq-Vc(iUA*3 P8”=£q2"ZhU}¦…IJkÄ@»q£søùÒ©-P)Ÿìª‚Çõ· øë·ß|C3òË…“o/ Rù B>ÙšCo=´´âæË,½šû!eðè;ËhˆíxPŸ¤þa±4¥\šwY[ž0úôÐþ¤]øŒæ^UƦ’š¶/5»"ª~NR=U’ˆµ*N˜…ïwýyç-–5m[x›:÷™x2CWPI¿'@ŽjP\†*Ày8ÊhŽ0'~»¯ï§»Õ„$Y¬ÆŠÔUÕ­õœÒ0aäÍžÓp¹w¤†j1ì¼l]¢L¼”׌E¿&\ÈneØï5Bp!°—SÌJ¿Üö”5Ö-2fbásÑjÿ ´à°“—æ uD`Ó©|æD¬SK]QVtëWùâp•:ÿ´~ôØó`Å9H4½p„Ãñ(”£yŸð¾CËåj2+ê¬9—Tˆ‚ }|ÿ Œ‹h)˺&˜k¤Ö|$ŒË1|ÿ¼fÔhnz†wü¼_í‚8‹&󯜉hìÛ½v³ó(LÕ ëßɇ-«²KBLP+–Áž¦Î@TÊàBš@¿µð€)‰Xôç¶v¾ãcõ;T¿ ʽ_?xD¯^ùý ÞŽWu›`ЈQ££¯Ža*û”3±k‡ûú:±áÙlÑ{}NyÚ]°ÞÖvþ:!]˜^†?îq.5æØ~E}25¬Ñ@ðŽá˜baæS|d^#=x$Mò"?gŽQÀÙ·Í‘F#¹EÔ ¿órÁá+`›Û§²s"Ö¤"´M3/°Hü5{ì|ä-÷å#Æ{nøùD'Q ˜]ŸzuEO ªî`ÄCÙ{¬î7~ #üŠ¿©yEwæê…BÛúRe!¿_8w:¯!¨¸WT¡¼â.Óº…¡~QZztäéâÖ·Ÿ—ð©õ’EýèÈÔ•º¦‹±ëü] Þ0®]¶”º]Ú4‹µ}‘„Z”6°Ì©-§Ò®g^€5Ê›¿å§mN³±¾M¾¢‡{ï|$%ëYñs;RïKôJƒ6ä ϯÝû«uµˆGX!l0ÞwÙ'X( ‹~m ¥k-,vбã2ÜçÅ>=W} -‹6\y÷£ÆKÅØ{\ЖÌðäVúLp½¬¾ÿÑ€ñìò‚tî†kõnÆ?á}¡iû6­‡‹¼ûy¢ýúYpzÅ\n[‚Ë—Ô!5½=W‡¢xQ†¬{®§ë.pð6IhŒA­p¼¹9ª³I{wIĹØ;Gå"Y ,í.Nð^±ú-´aüòÇŸüV|Ûyâé!}ÿbrKq(úbɬÀ†#™~-•C²ø?ÚœO° endstream endobj 17 0 obj << /Length 2302 /Filter /FlateDecode >> stream xÚµY[Û6~Ÿ_! yѱ"R¤.íK“ Z´(kì. E’ÇjdÉ•äN¦¿¾çFYr4élÐ…D’‡çúñ~¹»yþ&RžRAf­öv{O§:HS/1>©·+½·þOÿîóÓæÝ׻›ßn”ÂOy‰†i*ˆ¬õŠãÍÛw¡Wý/ ¢,õîiÖÑ3q ߯ûçÍ?n^â~f±_š6ö’0 Tñv¿hân05œO…fZ`F³¶ÅéTtÇSS}äÉ‘žON •›T¥ ·ø}7ÊÇÀ6D’金'´]»Nlèú‡¼Ï °šl‘ÂãL„Ç0æý8Iy[Öa9s‘ŽIºo$4WBâB\&L¯wi£eâ¾B8Ÿ$H 4 $Ú‚{ïÙXwuËýû´XC|á#ÜŸ­ ÊNQl¶(þîP •l|Ù5ï‰AŸjr%S;aÓY):’´êx «ÃÄcþaãü ç[[¹mj×ìmµÿÓëÿ`#"_7 «"ÇñSyÓ㨘54âí#owí$׳·«²Û 3süfišnø¢-º3›²äÙ»Õ=u=»11 »]àgIHhí!{¸%,ß“ðUëfWܘ8‰È6†Úx¢óžÕïe?N4œÆBvH©«Óy+œ3Üx%™3ƒ&-t°’2¬`®Ö3‚ÀˆC¿7I@<e~A¶Ä–˜Ú˜pÙ8ô(fk ±6•]_=³€PÁìù®Ð$ƒcã”÷û(Š¡ë±¨‰–Æï$eŸ²(—‰â ©8©#Ä&]zÍ¡®RT£á÷D‡*¶/L²?@þÀûCÖa,QC&½@Tßýøâ%÷y•-ØbùIšú¿£¸Ÿ02N!r™1×%\W38¤ÓQ"›ê(uÖÅ&Á6új–Ä&UÀÊ`ñȬó÷›^Vd>)™PËr®b‘·€l.{¡êJTÇ~ÅêÕ}×+vÊb8û_bXjBmЪ¬¡lcj{QÝbÙp:§1 *Ÿ‡;?îÚÄAh¦Ý¿s<×ËI(ç«4†=oP_ävÁ„ä6?VL…SòÜäèÌB}-~·Ì°íÆ•Cø·s7ºc¸vçõT8ˆÌ™aúw»ãçóHz™0šù¨ešËuh.ú" Ü+c;Tß=aâØ<"ŠlV‹\´,¬;¦ rXõþA(%(M#`îÀ«æ"‰ñç©€ý¡èëÓ8p‡T%wä2 gPS9·ñ-çÿûÝÑeãåb0,‚‰KuýøY®¢*ß öŸ?Z‰ÙÏîÎç- MÁ-ùµˆè„":u݉ŸqÂg ëÀf_Õ/¨ØÈ èë¹éÄÎÜM#ƒ»h_åxÉ#y3¾öÓ²¾¬[.½¡7? °OåÂí-b„(3¾ޤ+Á «¿¾;ߤÓÉÌÅÉ ±ØgÕP—hì\ÈíÏ=»ò{îŸzÁx¸<@kv¼®ë,™ ާk»–kû+¾¨ó‘4]ÿÕìú¯?s]'Ä4&•‡˜QzÈc(Q?2ißõk×…R™ä/†¬‚ð˜"ZNmÜi„¬v!;0­–ï]ý;p­åû¦¾;÷"¨‚¸OÃлûÝ'LUÒ8Ð&Z¢Êüâi.L<+\Øõü=VàG®4™€:ܺ«`ÉK».¤»'s·ÞµÂž Oᆥ 0Rغí¬¬«0«³Äƒ¡æ©œª+åJÞßgùɪ1z<÷-ÓæÕj©íy꣑’ã›Òüy†ÇXw“‹+2È€@çþPIZãúƒ¬š+Ét:N‘Ë!^V²N®ÁßûNx¢ß2!*ÉF¡:â´„qàíkCÿ_xš€4à©ÐH!XGq˜Pòj§¦ŠbàY÷‡zzc€®T³ý„[¿©Ë5Ö¥x¯F ¡«’æ‡øºN|¡›×†ÐŸ£ö™Ë¢6dNàŽ¾ºb&å,´jÙêVèO‚c瘗*êÂÄ.BnXSé“—d^TÅ ëB—8ǬI±×™ßþè'g–k-gÜ0Ö„ƒxÊQ À @é#õr¤¹‹$‚/iº:^E7òÅâ âæ˜ó-õÃ=›-•ܱYùeLÞ髯\“¢æÄÑ=ðÃ=™à˘€·ä^й‡þ/PlyÁ¡·¸Ÿ/G,›Þwx-ë(Á8 FðÜ<`ሼÙ5L‚‹+ÊL[¿(¤+¦t¤À7ë—W*P5ÔWøLgý²ûïªuªéxÀÛ·k'ÇvÁG*‹!¢†u¸P*¾¶ºç1ú£)èqô+”©âÙN‰¶ÀÃøv*Þ§ ¤¿,ÜkÁÚMÅ&A–NÇî·":œ´‘M§Cj3ùû€ž’u‚oú`8QåM_þ:úº@³a endstream endobj 20 0 obj << /Length 2679 /Filter /FlateDecode >> stream xÚµkÛÆñûý ýB%Ö†ûâÃFØF$HZ>´£àQÔ‰1E*$åëõ×wfg–‰ç»C/ .g—³ó~ì¾»¾úîG-WRŠÔZµºÞ­T¢D’¬bcᑬ®·«Á¯ÿj³ãúÓõÏW½¾úãJ®BøÉU¬`™ÚÚU~¸úø)\mþó*:MVwnÕae¢žÕêÃÕ?®Þá~&œî—¡C³ŠÃXÈDÓ~Yo¬´Áõ¾h×284‡¢/ÚoØð€C|Oº¸ÖÃò–×ÿÚpÛœnª‚?,Ç¢ÍúS[„0'ß CÀ½šR³‘Ê‘³QF˜Ù[o×­¢ ©óGqp·VIÀã}¶†ÿ/HFË÷Y½­ ÷ OÕŒê¨2ÁïEÞ¿ºD™ûee͸ã ù´a\:˜)¾PØÀ»†q‚‚eptoHðRlV6Z1·¬ñ‹ëP€4ü2dÙÊïÍ©t·rŒRCD¤/–v‹D*ÕÂn~³Kò…¦ß“¡mtS›ÊÚéP'`å¨KcR޼Ð;zíýꛌ²ÂÎ’€êìÀ#"&‰Ç/§z{CÑ‘“LÈ6x)J—ð¿Ð£‡´{AÀ‚w~-ƒS¥zTñ¢È•‰’p´”ȵˆãa —­©o°©W6¥ ø:dëÖÃj6Óú 3vy1Jç"éÒ¤tãÀå¼VA3C€Ü1 P*ð‡‚ã¾´., À˜~„‚¬‚, àWdN©vk&it[T˜*§JNT‰3\÷ºøS¸*  .2Ãs O;þ¸ßg½Q9™RY ŒôMÃ|-º„–~“N±Ê §ñŒ3Kü¾ægÛ2½ 8dÙØà­ƒÅžLÏ ÆEJƒ%qXnOÎ9F‹ÆyªÖ`´w»}ñµ/@Šÿ«2/ûŠ×1Ôº‚æ ä±-±>¤QYƒk8ll’bAêfÈÓÆ ‹»cÅï»¶9Ì8°ƒÒ¦½Jß²~N¹O¿Ê;2’ XCSä?8ÇŒzžèžZ«—uƒQ{–œÄúQªä•è|riÞUÕ-fP#mÏ ¡éÐù-¦a†8¼LŒ„Іâžl–­Rïéá<ë6#­ ÿ—‚yìi}§|"Ó>‘áTMy±ÖÄÐ|hðz1$@¯cÆŸ^/àk[„]ÕdvÑÓñ`,_ì5@9ãÔãxhYdmõ3ÈÉ!E¿9§‡øz¦xNµbÓ³1‘±9¯dâðqÂbÊaË›¦©$,y:àO«Ë+‘@í)e*ÝWne´ˆRùµ{G¦ûÀùéσh„´òQÒ“©n–hW*v¹ñhW’_Žö©Ø#³@zlÁ â!=Æ­ôÏûíЛ ¿íZk‘FíǾݖ»Ýñ)ž¿¼ˆÍè\P?ö懦Œ»ú -*1é¹®û‚tc(ú%(‡H-¤QOûÐsºò;ÄfAMJÌôn=çn˜¸ô$ºVÊ‘º|Ø©±ßV³Zf)¤@—$,´Õ`<2ùÿlÛ‚{àHå{’~Å´%j4$âŒue,P¬//“ÔY¥èúȳƒÑó;y'<ŠùÛ£é)V…W‰¸/æŸ06®Vƪ„»Ôÿ¡&My endstream endobj 24 0 obj << /Length 974 /Filter /FlateDecode >> stream xÚÅXMoÛF½ëWðTHE9Ù™ýN P¤ES=¸>(³ÐW$*©ÿ}‡¤H‘ôÒÇk¬†3ofßÌ[òítôâBb„^kЦ×9ç"«4/.š.¢Ëñû¿w³íäjúnôÛtôy„‘à?Œ,±‚Ô:š¯F—W"Zðþ»H€ô.úZX­"e¯Ëè¯ÑŸ£·Eå  ÃÆS-ÆIœ.B!¤oëÔz «(”߈x1߬¶Ëä¿dRÊ'Ål@}Ĭ‰ùúbPçùr¶ß‡0JÆÔý<¿I—‹|ÜÚÔ¤yL8ŸXu E¶ù TÝ_ÿ}" é“¢íé –:â’gKt®ðt³ßæ8NæåF–ßen{AžHG53¿Ìv}Çd-(­îHE·Ö>Ö"§¨ËCÒCKÍëÛy·ni:„±¶¶ó`pŸO}FÊGÃ3[%F¯]O—´g^ºÞ²E¤ã^V]Šˆ~ŠlY+¾ØYÔ\¥ëÍPá-ñù9Õ™¥M¶Rߥ‚j2ž;7‹6›b2ÏR¹»7ß™áÎÚ.ê¶?V!rqª3ü9%ÿkîØ®Ó »ÚOϲ6¾|xÖ/ÒUø%Ä _Y]=¹ž;_ÁuUþ¡I²#ê…ߘ4ùZZy+(­ŠŸv¤µÇ£PHßAZŸ¦ë¹o‰l[ØòLbòhÎêõ¦„t†“åñGXÄo¬ íB`ùVU ’íP/ÒO‡]RJV·öÖ7ÍW»Sýë¯-]çüþŠ'¬óÙrY:Ýß–ŸJfÅ 7 |>Ò=Ÿ+‹xa®«ï7ÿ!Ø-c endstream endobj 29 0 obj << /Length 2829 /Filter /FlateDecode >> stream xÚ­ioÜÆõ»~ÅZn¢¥9±Ó¶Û ì…UôƒcÉ•ï’k’kYþõ}¯%ËE @3óæqæÝÇìË‹³§¿µRÊwa¨WÛ•N´Ÿ$«Ø†0$«‹|õÎ{óß&=¬ß_üvö‹³OgjÀŸZÅДoÂp•íÏÞ½V9À[¾qÉꆰö+%0îVoÏþ}öï³Áô¾Äú&°«8ˆ}•¾ïÉzªÐënÅZyy±åuuÜM™áÂzÛ]v‘ýÐ=G€ ==u£4»ÑÖ·°ñ{“—UÚÜ®7FG^›¥»´iq{Y UUÝñòr½ÿ#Û"gpÚ2¤>v‡cÇó´¹²ª5lw­Ï´X3¥EÅ~: H±“ò6[‡‡À).ò¸¬Ëª+€¢~’Àwqr¤¯ÓI‹cø é„ïèú‚¸‰#¯«y»»¼¦ÈꫪüJŒá÷ÒD9¡)«¶Ì€M˜DÞÅuqËÛr!pÛ¶ðY.Ç×Hêjã?4vÎ`Sl äÍF‚v*0œx䨮Š%¶µöƒéó:´@J ªJ/wÅs8>D&ÓŽ/*Ûsi/• g†TZ÷gåõŽøqéRû:.É0ÎÌK”ñ76øÇéQ!¸B¢†£Z¦3Åá®òiш!4¦T8¬xÜûì8QÞ9«@ÇÆ£¹ n®A»pô5j)Æ›—ÊØ,·M½¬þV2ñ&E\qœ?‚0X°”‘³O$üîý¢ˆ¯Õ b8P-zÎFãmð˜5¸$sñ¢ÝbÙ‹àZcæ^ ‘­Â‡…RÀÙ}aâ>úÔ}ttÇ}–x‘Ëg¬¼XëÐkˆðôv‘d“@XÔ=ÉmWÑVJ!£R^½eøŒVXÏiÒšL]Ý&ºwuØÞ§¸-‹kºâóZ‚!@Š/‡]™•Ýî–¯mÑŠ¯ÈЪ,…k¶È0ô!9»¡˜D ‘²-ë iŽb²$2é¨U†â–f ³ñ‘½¦èŽ|0®«ü}ˆÓ„>‰ÓçC|¼]ŽMÖOâÁ½÷Ƕ[ÔMà&ê±f²"Xk}§NT> KX€ñ Àœ¡£¤Ð9€\«"ï’x]–•sˆe  ,­)ݵ5ÏÆl†àcWïÓ®„ìד}öeU°ê‚9Átï,¶¬H¬ËÓ.E ”÷Ï-ƒê æ™|0°Ãp E8€ø¦&±•y‘›ÚFƒ’ƒÒr.§‰6õ’R>¯ ™ìv5±›¥Ý2?}ÏêÝq_±Ç^“ ƒw±ó.æläÏCÒ@r¬²ŽXB EW€æE‰ÔPŠ$0v ©|1ª°¬Ùæ%W'4.‰çœšº«Ù‚ÓÒ_bIýQ*ƒ]ù‘"ÅRù³Ôq|®Ëœ{—tBñë2v‹™/ƒ˜Ýñ®T£áÖc*†ýGt6N45‰%ÊÌ Xï§›žq6æXH—³T¾²'ÂN³§Š$©>©yHÃkQV˜;aeAqP¶ÏÊ @™dÃ…P}77Ú ˜äFˆQÈÑ7ˆÌDõB‰z¯· –ý€̳»58B9‚ö÷qœ€ÖÄ{£½ÁJÂë ÷Vç›±}8¨»q€c+ù·¥I\¨ÛÇØJ!£æo1¶j‰­K‘!†9”ê³TñªÞvÅ—{š'ãbÇ @dMÕâDèãtÇvsHäEuU`ma œ¾b£ƒdçœ;V È˶+A-ršÐJ‹Žâ´”¬­ôNTiáI À[¬Ó^[ï ž½JÀ~Ïwåe}(Å0Xæšg%ˆÃ…Ö©>¬­Ç7…F>ú\¦rE×3°·ÍÙ®£p­m!ΘÄúÌf“Ùýú€¾g}›Ý,¸±!Ô§2ØdÎ=t04{[8¦WdŽ®o¬îÖ¶ç‹}yصöÍ=^`¬%îÔ œÔ³ ›±¤è¨\1€óEv‡æÖ‰A!±euµ“ÊStØÓ$ŒôEì©--qƒ/Œ <@˜Ðÿ&£× IKýµòC34ÍÛG7yÐÚô¥²ƒ¬\_[®¶pä2ß°Ó!kSÉçp‡¸%"RÓ~tZ5³|ùN¾!èèž°˜‹£» ½7ÜòÂöUQ é"õDwÃùö±Îï(Ü,œ¾ì‹¸3})q,¡…8ù:+ÝQ¬ <õ–t„ÑܫˆŽPC1±l4<²ÈZþû=ÉÀf #9ãQ`‹vàœ«¡ïÄWRy"µZ…õ}ËÊ´Ÿh{z8÷³Pr8ôôÙ!àC ˆ{¸õš$Öûkz”Ž!s}Iá¬[Ï™ªë`l 5M¢Bè¾¼º–ú—ÇVàœ a²­wb(Dõ× ¦ÔÿBâ¼ì ²Ú…ÞñÀcÊÃ6`>±¬Ð›WŽKµa覯|»(0ú6±“w±`fš!·™0ŸŽ¥T9c¥”Ô2.çe ôrÑ£B`š!ÞžÖÆpÅÍuQ=xú’¯œ=M+ç+r±™§•éûeL…*VÇÏïAëÈÍ«ð¸È~Eˆ# øYèøeÉÛXþ ¢íògÏ仟٠~a‹%¥>_oTh­÷ô)ÿ^lËJ®KyȰãn¸Ÿ€'xµò†Sš"Ý} »Ð<¾¢$øªaé# ®xÏI2Ðó"ƒ¦ ­1jáa[ô?„ã'ç +÷éÕwЃèß Qèxä«)>ý5—øÅMü ¡("zûºÀ‰¿Nè:oÎË‘¶¿2Òߤá’ÛˆÁ“›tB©ô¡Ÿ¥ò­bíÜ.¨wJôhYSóTAÙѫޒ«Äã*êîîsZA,,¡ ÔvÊ=ô ñ#ªîýN+çCßLgO߈aþ!´-V|@üXÉõævB}b@VúÏ¡>‰ è™ÿ‹zhëÂû2¥P5>Œ¡½ÝåÃÄP¶±&N|0;||½/“¨ù/`YÒäÃì’Ã…®Û¡ zLW:*±Ï¦‹Ø'vS±“lï¼›¦ì žJÆvlÅ4ãæ &hòƒ-.iÓµrÐVPyX¨ìæxßLÐÆ:ßÙG$è©y`!åâÛr_Ò[-ÞÄnLÂ0 '˜û6%6¢›ŸI°KçêWZüÉ븼JR=É‘ck_ƒù%»–Bê‹ü˜u÷U«ÿ}kvšÆÂÛ·Ty¿Ë>‚Ðs¾¹Uý³',Àþ©\Œ«~—>„NZ2XÝð‹%>Òq+°±°˜*€é=ŠŸøp9V^HÌ”;úU'ð&ÕÅÉKwtú*?¤Õƒ¿ù—ò¶’öÏ.ò«`ìµ)=´ò‚ªÓá' ¼¼ÉFbÚ¬´ñTzË¿êÕ6£iøerTІhÄ­Ê×IÌŒD}ÀùQ²ªŽ endstream endobj 32 0 obj << /Length 3104 /Filter /FlateDecode >> stream xÚ­ZK“ÛÆ¾ï¯`UËK3¼â“¤D¹d+‰7僬Ã,1\B"½Zçϧ_쬴I¥x˜÷«§çë¯|ysõÝëX­” ‹$Ñ«›ÝJç:ÌóUfHòÕM¹züøKkOë7?\ýõæê·+µŠà§V™†n*Œ“dµ=^½ÿ­J¨ÿa…q‘¯î©×qeÒÒÃêç«\½¤õò•2alRZ'‰²På1¯eB½Þ(¥“àç¾­ê»×ý/7­6Z‡*Íx̬g¬/{š(Lu¨£mÝzc” ^mº~­³àá õZçÁùpØô®=Vµí]É [ì¶·­ÝB Wu¼\¸Þ¤yÜìÝ׳w§õF¹mõk¤Ì0Ó--Èù~ïd·3áǹ U¬†íŽr_žjc´ ³tµA“ro>,-R‹fW WšŒ“où^¡Åa”ÆCG8§Ñ:xá2 Mþ¬)ÓÐdÙÐq¾ÕÎÓ ZƒÜ8[7=gÜoçê÷u’öàjBõIÐ7Ün}[Rq¦I>î îîý‡'T#Ö©wK×&èªzëdɽìó`{R¬¬dÃ}ëHa`‘Õ&†%òd¸›DzÆ* l-iÛZQ,6;L-ÿpm#ƒå wO[Ó¡£¹&ÖØY§Áɶ}µ=,® ½»ê®†ЫØZmH£U&I1Ÿâåm œ¤:ºº«šºÃ²¶(Bl¸´kQ€Xé׈D‡Ù…F|AKsÀ¥I‡¥ÜçÓ¡ÚVýáWó¼oè…òÅÖžjf{Í9QuäÙøð­rÒ×ÙñÙ;¼ cèB!y…I,ÐÃUtž;RÈí芡[sîOçþ 9«.6wÕ’#}ƒTšâ`Û´­“c5u9®±@?¬º=ácÔÃÖÍF§¡V#xÏ´Ië®d||·h¶%IX¤ }õí{ÜE‰Î¬@SYRŠ%¥YRêBRJ$¥GI©AR~T2HC‚R"(=5ù¥QPùLPZÅRZ¾nßœ%¿‚»xzò\;ØóFTÞìP­HE0Ùëm…KŒM&(ÝÞžKŒœ&h]nëÙðW˜ÄˆÁ`žàzY|Ô¡F3·@C—ÃÙÍ×ýé_oß^ûmœ“"ûª3E˜ÆÉÐí¾:D= !+Ô\ž'Ûu,·[K:û‰K|o=[+0”Q(ë͈ÜP‡yj y÷’ÆÁG€Ðç‘w·Ý:‰‚±÷#«“§ùŒàd)¶•Øî¸ê¾ê÷‚däýÙNÆ,¬(=l8°`@¿'cƒhPÏž}<=ûÖm›»´]¤¢…ðåtÕVà-OÓN=»‘CÍ®äøù¹¯ 2`ˆ£àÝmú}Ûœïð¼©þ ¨¢s\–‡qhðÀ÷h­€“$°Ÿ›==mèKP‹}Ζ\…ºŽ5]st÷{ÛK©£tàw›¢ºó¡ï¸ ±± c€`uã½ÎŽæ>[ÀpçUoÐÎ$K¾ªÝI&z´4ðH«’î=Éý6 ú,–àé×d¼47 5p²/Pò8L 5'åK¦¨Ã(Ži®æ†ä9‡›agÕxJʇÚHP¡[*‡Ïˆ+zRêÓ`± u­ß³Ð›ç±5š^Ì °È¥îÜžÚªsß•*`7i6GÉj'«>êí„ÅôÂj>.È‘åD™kéD¦íD .‚7™¸JT ã&,¦¥…y]¿oH—…¹1Ž.¸! Ê üÆÜÿòD¤‚Gûi=YË(¹mNÒ }Û-@”Ø'#?µOåŽ4È€4Ø;Ø/@öÚžFj+³Ð&Ðæ*}€ëã‹êÂD`½°àvŽÓzK‰ j“Íx1qzFú¦u¼ë¦Þ0¡˜Ï7À¨±¡1ÚÃqáñ{–ɳàoe!ç}íVÉ45ƒ‰ÞˆÂsÚù‰Ù|ÃèVr;¨JÉ÷ÕÔã*¶-ýìæUÏ‘‡.Š·€ì\s¼O °½4v4VôÈÖ©E}C«ë¤eDZ6BÕÃuó)‹{G*.†‘±Ð‚& ³xBãûSßz1;ºô)êÆ˜–o ˜™ ñÆÛH*ÖM«ÉÐüUÂÛcW§ÒÙ ÕvÃÔòtÔðù`¾ø`–‡¦Hæ˜B³Ãƒð^ªKEЇ{ÜZÓ"Êg± ÞµEª[Ò‡YÍß1=wN*öLÜð,x¯ŽèqÁÆê£Ý¶×2¥°U5ªß?uåïÞ=ñÍHM6ŒmD×óôÓ7*ô€ú 5; ØFH*Ì- ódáå—å›2¢äðžVîçQ˜ç#sÜüå {OŠP§£NõÍ´šgâ67E®î³×‹¾”ŒÑ”msÂ"7ÿå§òʺù÷›ÉIú¦ãoÑ·k Ha˜KÍš€`be¹ñí]{J,¡yu¥ÿŸÑà¯Kþ:0v䈀÷‹A >a‘>ÿ“AJèêñŽñüYÁø‡™‰ÁB¿øaÎJ?úàÇYrA0rE݆™óqfÒíÐÎÿM˜Í×<‹»Â£_3!È ¸`Áž©É†þÅ= Œ endstream endobj 36 0 obj << /Length 2332 /Filter /FlateDecode >> stream xÚ¥Y[oÜÆ~ׯX /»Ž–æ 9¼4O²Q ’Eä! ŒñrVb¼Kn‡\Kê¯ï¹ —¤([haÈÎå̹~çî»Û«·µR**Ñ«ÛýJ:*ŠUžx«ÛjõÛúç_½=mþ¸ýñêo·Wÿ¾R«þ©U®a›ŠcV»ãÕoÄ« æ\ÅQR«Úu\¥YÏÃê—«]½£ûôø>$ç‘*¾«õ›mbʵíà™Åkïú³oxîËÆ¤k{8».ÚlM’®ÿ) us:÷×ÈáÛi<&¯2Åeõãã÷ö‰wNIó(ÉTØXwLùhO§ÍVkWñDßòó=³×ot¾~Ú¨µìZäƺÌé]Ût=ð¯ÒÀΛ%~Š,Rz8ô=\—gëVnÏ}xµMc´•ZmU¥i&ÀIœ³ q±>Y` dY`·PQªŠ™ÆÞ,òh è¬óBÙFȳðd^ãªú?øRˆ©Ê9c‹¶,#­£ƒ³¤º\ØšÝ ®pöx:8aª¿wÌÍ¡n€ŸE+n“¤ŒŒÊW[DY¿ ! 1ѵè½j?víÑõ÷us÷{lâàwdõºùhýÝ5ïdKNÜaXÀmpZ}¿$ãVé(‰Ó);¤UO¶¯?P.ðÐP»Zßó‹å=ûs³ëk2¼Uî÷X¥ ™÷t‹&_YÎì@"ÌœÝÌ6N”pq2ZûŸDÿGÛ£°‰kZt²$Y“Æ÷ÎVÎóõ°«Iåi28™{Œî—XHÒ(O.ÛÎ]ÏÔ?3çáÚºÙ‡sEš…‰}ë›d-,o•Û¬·a"aÈ…£ý¼ „5„CAÆFšgSè\Ó¹ˆ6¨<2¦œ.ß’Ó—@xn}´þIÞÏþD"´ì`žK#3l± m8d»ŽG¤tßžïîù½ó-Ó°‡C‹¬?ðk'±¿«íÖÿ!EÁ~ Ñ×ëäæV$]ăiQ)™ðƒš´Ó;ßUšéúÖÛ;Yn÷øÌ×?ß (ÜþtóN6¬ïdÏÑö¾ÞÑý°™‘-ÉÖA=DØ“P„«}¸ÉŸwy®Cæ9±:Š‹†Ø»ŽÂ‘̵¨Ëñßïê/V¼ó|â'K ‹ihŽ/ä"Míšã$+*ã^<~–ðó2ŠÍâC®†õq¤Ò!?î½=Ó¨ÿ™ïq‡Î=€Øåàx±“4øÔe¤J°„ŽI$ha¸Ù*¥ÍúæÜ·[”!Q üç|OžBDezý§ÛõÝk M­#•åLô‡=ƒ9ZÄM³åGcÁ<ä˜,À‰5 ï{ßy„HÆ£‰ŸÀ{e{Ë”cËíè¢|ýþíûï¾ãÊB¶Rü²+¹ë‰[ˆ_?‘~Ͼ`û%àŒãå… Êíy¡'"àá°dye²ÈèWX^A%2dÓ@X.ôàÙGfÄ‚ !hêo ‡ÌÑ!!º}p‰85B"V”ˆñÐ%cŽ®÷åJÂ̤Su<úi€[ òj ÉA¸BéÀõ‡¶]MðÈÇ¢!ñÀ5ÀÐ àèò‰g§Â‘§â4øì9ò »»®°ûàÊÈ}ð!Ÿ—‚vµÍ‹(/gˆ®-y;(e·çCů¶ª.‘O3PÞ¸oæõieÓ?ˆD~5JÕœ¨A«¯Oп"šAõš†ÌgÌ8×-—ï÷Eù-#ê(+Ó°igr‰¥àÄÖadÊ'^› ¦ L,𣕉ò¸xe;ë±g!]ªÂ\¸Ú{· %|™ræï¤™¦blÊÔšÑ=¥ÞÐtP+Bå,‰ïÀ¸”Z&?ÙŠøYN/ØZ›þ^)\ž¿ q Xáâ–šµbýC/üÉ&(ÎG'üQͶ€Q °.(r¢™TA­6-ü!ÛŒ=4j¨àÀõ¯ïàâ¦ç™öÓŸç^È- ÒUyQ *tá^Ä3Ü[µHÐÉÝMnzhfÜ3Ò྆è·Ê‹Sa_£¨ãP£ºÂ½³%ðÒÝ{%¤G5Ãæ«,ÆpW`v!,ƒêƒ0ç˜_ûáZWW2Å%©;uüjy]tLÔå‚P ¿Ž‚b¡—ºo(zf©dF@š:ïø~é¬/ÅòŠêKØ9¿uuØh‹·Ý_›\@c¦  îÁ~8ûˆ¡÷wׄé¯6xVz»ÑçŽÝ½õo„–º»¹Õ¦dŽtá/— /ì´ÏI˜Y¾íïþÒÖÕìàïÜ×îþzî+‡æ,è9<=_'ó”£`@ßw‹¸s|ì*g¨°Ç¥Fžƒ7ÍZ:+ãXÀ缜Cc—Ïb+´,Ï=ηÇnE…œOu ¯J¾vÁõ’ÊœKG=ö³ÅÏcT¾4ÐZ§êZ'Ê`†àž3åð¤ Çúƒ'­§ Aà5¦)?‚ÊÐÜŸÆÐ‰fêVŒ›y!|‚SB™Êñœz 3°ÑyO0S‚4»³ïx­:{Ò9.b8ø‘K}Ù$^á@ç@ðJ.¢$ÌŒÅÌÆ£Ä`æ^ñ,è(q5îeÎJd(!Š]×Qó-5/ðO_å U¸ƒŒ†‡CU@ÔéKxC:ª¼ƒ¸¼C|€x!²j ü6f{ª…îËå;Šªg§w@oçN‘X è—·:…–S|[÷Ë(»ôÎH[ômà»,ž;w’œÇò§“\¾HÃÌT1=OZ9>3ÒÜÄ»iÕósøØžÓÇvCÛƒ_Cû>|d6£²vúâYTЮ[)‡=€µš|]«iej†Ì/鵈ÉÓçzMñ'Ðk U4ëGÔèâ/ãdÏK–WülC[ÝQdöô  ¹…¢œê„`#":BÓ;õÓÁPèš#C±št¬¢"F5•—ŸgŠðÓÌ|ºà endstream endobj 39 0 obj << /Length 2647 /Filter /FlateDecode >> stream xÚíZ[Ô8~ï_QÒ>P%h“ø’‹xj1‚Y­èÕ>ÌŽVî*WWØTÒ$)šÞ_¿ßñq’Juj.ñ4B`—cŸûͼ¼¾xþFÅ‹8¹1rq½]ÈLŠ,[¤Ú`È×›Å/Ë÷ÿjìÝê×ëŸ.^__|ºˆþÄ‹Tb[,”1‹õþâ—_£Åë?-"¡òlqïwí:É0–‹ÿ¸xéï“Ç÷e‰PQºH£TÄ™âû´X]êÌá.“DÄq2ÅþG×CþR¥©H¢dqk¡uŸÕÍÜÙØA¬œ}"ÖçÏ¥iÞ h î‰3!s‰I&24€$q©2³$º³e]T+ ­%ËzË0{èêË5X â?Ó?®ñ!X}³º4fùq/ݺkùÃ"ŒVkž¶Åþ®,¶üÕ=(`N»†á×·C·uX\³œc@·³µ½ý¯G$– cò)+wÎz|éÆÈ"Ð$…±ÛÕmËÀ²§yÈ«§Oy™i]wÖ¥m[ ~ü;2#Šî‹yk1©8XȌžö¡…Zñ|Ãôà–²šhAjº—ZUws¢•‘ˆrÕoºkjOd±qŒH· ,Ñ1¬5I§ü‘ ð›Íš…‘oÔû»¢ô¹–‡àFJ'Ë7dµDC@yF[ò᤻fˆÏôÓòÐvX¾Øúè¢~7h»kšYÕHDZôŒuú¾·RÌ×6Ë}St³ÑòÁ&ä9Ÿô7È%F”5`[Õm)”zñ2€1zF?ôr¨cØsuK–-ÙUoUé_Võ½­*ù˪¾·UeßɪÆh•H{AWšUoÞþüã»×‹Ë8AÙ†ºß!§¿Ya -ói9½3N•ˆŸ¥L`Ä«wW>ÌQ£QåƒÙPâ4GF,bs”Þþð÷¾œ#é¼0Àî[¡«ç&?OÆ´r”$~JdŽ}ÖKJCr ÅßÚC‰DmFo‰‚y(0öT„±D*£ÔÜm(ke4ÔÈuÙ‹­¹Ä…È’i‚*¢ò¦ëתìí™àÞz{äckå©þ7<ƒé½LËKÞŸa yfð8ôËô$­Ýž1J™èß—&”H Ø‡Ts‘ëßl{(ÔñciÝ©pF”û³ÒÞgœ•&"ÅèñÉgEškGj®r÷>ï'ÖCAÚpj ŽSU1è ý2‘1D®}ù Â`?ò)Ùÿnq¤À¾ákß7!¿ÔÎ6oŒHGë:oÿ:ƒ£Pê›°Z£dÖÒüQVaÆÒy;ßk¹ÔF‹ª0qùÛ²¶ó^¡Êž÷)G‰C,ô¸iK«t_f#{,²8ÍP¬ÁòåUèpÁ™ÏSEÚàÁž¼­>۲ذԭ/Ö½ÍÛæÆXu!"ô{~ÎDLKµ¹:Ï¿JnòÒ±ög©©A*õЉày¼Óy2Ë6 f~_x—„:õfH¹µÛƒwZ[-ƒöE»·ÝšØ½s¡¶|o»9Šßvì™Â-×Z}IŠ…Vš7Î+нÏF’|̚ƭ ¦"ô˜NÝmJgŒ}÷ j¼ïZ¡ãÔ¸O‡¢éq"ÈIþI­¬IMMm…påÞzœ0ö^9´!zÜ®M„6ƒó¢m¥›í!NÆNйg” ƹ©7ógQ¯CDÙ‰}NB‰ô9!Ù´GÕw ot_}#‚¤’¿5¡JxÍÉá¹ú" ±†LPk½t̾>{¦¥Ow ç­)áªßÜÁò-š0%ÇL`R\ºç@ñhQÞ<ë˜Êà—½û¯y6wºVb”T1Û3F¦7îÈÚŠi)6.¨25BHMiÕ·?i[[ïÝY–ŒNqJo–Šll÷wó8?‰/'« þBF"ƒÃ™h„mÛÐä/¸}¯RD®¢ÛñŒ“ ÂTÛdéòõñZËû8+OÓ#Ÿ‚v³éÏö†y|rPšáÛûp郸_©dåTäÑòÆgJ|ÄÃ\áaÇ½ÏÆíëÑ|7¼È—(Œkj¬:Û²#¢¶(Ý»n†V¯ì“ÁŽ·Ußõ-Bu¬•T¦Ç…Ž(ªp%Ó¬¸+C㜾j-17fˆ¢w·{ûÄ|cýÓ‚¨yÉÖbÂyƒvÙ&ì£ÆjiéÑ!ì+‹~È¡(ŒêflucÅãtô$åÝèN[§Cm‰Þ6ŒÕœCC(G&8&ÎþÔçî3Bî§0<²Ò(¸Ax+™#1‹¿*ÈJƒD e§ËÁÙù' ±¿Ÿ¢GÊßËePªäO’…ìG¤(X¿Yp|锬°-Ý9ºŒ (¿ ¨¦È³…Ö>ÊÑô$Û²sMºøÉq”äjjÐèéʱfhnCÏ…¸*‘™?É;E5.²!üIúuù2Eì,2þ,ba2EuŽuØ7>œ ¯:´]¾´L§eê7ô†„À \ÓÛ¼ç­B–#ÕÉ”÷$6X¡†·õ̤‘êš[[ÿó~‹–˜¿˜ðÃÍB‰]“íæH…Ï<'Ku&Žçù-gãM&â±Ãר×oLÑ#`À÷èÍ­å•_¤õD+È)V' UÕ Å¿ŽD3Ï?«Ä½óŬ®ï]Û»>éŒùé‹”Y„$3FP¸)ºàå¦?Ü0³[†Czº/XÁ‰Kþxhà FÏí[h??IJ¿È^èM­ÿy¯¶ÿM endstream endobj 42 0 obj << /Length 1590 /Filter /FlateDecode >> stream xÚ­XëoÔ8ÿÞ¿"'‘=º&Nì< TPB¬Ä‡RÒÄ» d“Ý<ÚÛÿþf¶8Ïn(ð³b¹£ÝîÆleµÞÊÍ㴦Ⴐhé †Û"ïÓ’­UwcX´l6 ù{̸º1goŠ–(Õ?éz£=pÕ‹­zwEYî%¥?Is´ÞÜ^óІi~;““S2]!—0 ‡/]  Ý¥t€SÌBS˜ Óa+K°ߨ–f:èá 87@œ9¥®8Xk“ ±÷áþ÷èñöÙ³©pß‹Nù€CºBÈeeÚ¶4¬é¢5Í nö—ôM‰ jÏ-J²ö#w7ZIÕÑû,-K°ÇDJ"fÒ@q£0Däv*ƒ%Ü·t€éxQÆ!ðjŠî†Ä’‰àÈÃ×…†PPxà$Œ%h‹â ««¶kzL6ZÐÂà•Ù-Â0´ÀMŠ3b°Þ¥^ÀA€Æ{×Ù}•uˆÛ«2‘ÕäjéY°WÍ2ÍÌ’-d0D² 3sž0qk¾ùúzÊÆè¡–j•LWž¿œ.’v4ògX8ppúŒ¢jÆ-ñÁ•qŠâ&©NT+JѸM‹ÕÍä¬ð™ÏåØDTPBc*¬CéÚT&¬»¥zLQyMù#äwÛç“lMó{~€v<7>ôc'†·½6!þå¶¾þqE\_щBsàU_Žxø¦Ü¡љ˫Éô„ˆ4ănåÿ¤µíè|¥îHK©úE‡QÉØ–Ž¿2<ï% Ó˜€¼qÇÔ§të§#q"`AÝç‚õd>eϱO c«á¯^0ž›ìñ;7äªTèm×}Ùµä<¦/¦SÜ, ‡äUëM·›ÄQÉü0°dHýnä6 Š•ÎË(´Ÿ“&ÅÄ×u]NB hãÅ– A$NÜë¾3´ã÷BÂ’p(ÃKᘥôX´G§œÔÖuô®êŽtþY  ,§Tj+øFуwIß—j šqºBèH4" ßc<ÇÞ3)Õ”P¨‹^CûЗA-\Ê<ÓX§xk*÷¦¿ÆŽ^ ½-+Ìðæ”ÁýýêfèÎé;à:’'Ü- ·ÚÑ8¯íq]&u;GÂ+FêCèzœËgò¥:„V‰ òF©ýd6< vÎÏ÷iÎôGú˜D¿PYÚ·“É.àõë !¹©'žÖ\̃w54?¼Œó¼†$Høø}±2„Ô ‘•ŒÅA§6 0‚ñÄjV)•ë‡e¤›Kü˜5ì:u´™MJ®²WæÚL—s?»YÜ/r3-°Â«†VññL¯ßÈ5§‘d­†çñþí‚[ÆÈà_³ä8‰µTª2“ii³ê×FªÉ°®¶/ÝÖ¬ àŒ{‘¢ÂÆŽC{1J áCàq’ìÿSÂ=ëË_[\ endstream endobj 45 0 obj << /Length 1923 /Filter /FlateDecode >> stream xÚ­XÿoÝ4ÿ½E¤!”·õ™Ø‰ó…bƒ"@Lc¬H¥By‰Û—‘oMœ– ñ¿sç³ó^Út«´Øwç»Ïç»ó{y~òÙw!÷8g™”Â;¿òD*XšzI$á“zç¥wá¿úuÈûÍåù'gç'7'Ü à{‰1ÎB)½¢9¹¸ ¼è?z ³Ô»3RÅ)|kïíÉ›“—h/ Ží¡’ a< ÉÖ×›­äÒÿZݪvÃ}}óYßõàL³†xÛµ û€ˆÁôV¤,Í©¿šÚBW]‹š"ÿ¢*OI§¾¤ï—ĘmþÈà¦Û½ƒ/_èã¤ïZvÛUåÊÊ3¼™Ô¤ž÷Æš«Zý)Qfe7íje©ÚØ3ô¿Y±(Šg³B&¡¯7[ˆŒ`Kÿfû•îz´ î@ìªFýüC*ð*ÌúQ][~P¬è+EÝÿ,xÒñVÜ,N€Ý¬j~B‚Æë°çG/­ã#¿›t?éGáÀŽŽDÒpaÄqó„I™AT„Œó„Pýñf‰ÿêÅ&þùO/^ž¡ÒômòHü÷nòçF¤¾¢Ù¨ÚÑugIUƒâS­óVuÓX›…±ßOãÞ-ºE 5ä5ì¼EÅzd›m%þ÷ï çÖ˜Wdö=ïnÝnŽOè +Á€ îß kq(ü¢ÎÇ‘¨]k±Œ©ÛªT–·ËǪ fEšÔp•Žm¶Š iK0êZE¬ó¹&™œ>ºjl1_ÑáY7Õ%-¸*­Öâ5Èìè h^ÐÖõ45èdêçeI„¦‘˜$Â{Eç$àÑf€fã×ÊBÌxŒŽ8ñw“å^u ªºžF=äºÂdxMĽ=Æ´iT6:éüÞvçL~?Š£˜‰¤Â1+XªFšïŒO”†“#†± ò®Òæa`<˜’QWKßo>'ëË"°%ó‹;´R 6>^ V Áv-s/+ÁA·Ëø.S—§Ç)y¥¤<,³®ñcEàéj°T}#Bs a%¿~°T˜˜B-ˆÉªÝ‹DdÓÞä95Œ$RÙ/&BÊt᱇ÃX°œn3í>o1ikç¦LòÐ ÛJköô~Ôª9¥š²§\†ûÝÊ-ì,†JY×T5FšSžŽC¬ƒ%uD)úÚ, B×ÃTèn‰ A` 0LòÁŠ`@•–8é®’…´÷ľ۫ÖiI¨jGèfŠÕ¢l N‘íŽ:%ôqIäë`l÷Yn à `-òi´BˆƒºRƒj©ý@5ÝBÝ´ró[â`îÁáã Hº' I1T¶S,mÿØÞë !Èn+xÇž˜hœ­… $ÉâD.ºƒ'U[Ôg*¾0`¾Zý‰‚Ð[ɇ~¢àiÂx–,¦€kÃaCA)ÄczYÊâ8Zœ¶¼Œe±ˆé°#ˆðÅÜ>ß›\&“¹ÝÌëÊÞ ǾcÛ§“Äâ“ï(•ÛäMcG&GvxÐbîuûí/Xh]M_@‚ÆQp”YÁÈholQa<9k¹åšßázjæJH0IÒ¾qà…{ö Š®i°˜QøE~¢OÒÞõn+>Ò¢Ìy%Ä< nžACeÛñ0”„¿vÞ×¹ÉŰÄ,èh¬÷¦ ¥½vùµ‚ _’¸-.Aœ$’€%Y¼’–ÇËYÏi´È-¸A5¹ nèá.í0<-"Û7Áèu¡st&åurUÈ…‰)ò•»©­AÎk¡ºÀSÖ¨OϾàGpÚHssA»,jöØZJðzá¨";üÆÇ¹»=ÿ¹ ² endstream endobj 52 0 obj << /Length 731 /Filter /FlateDecode >> stream xÚ¥VMo›@½ó+VjU‘(»ìÆ8v¬*RzˆÔCTK=¸Väx×1•ù^YUÿ{÷ )&uk0³3oÞ¼ÆÜÌ­Ÿ ôÆ„ 0ß"/ Áq Áœ‚…ýå[±ÊΖó;ëvnå¾øB0B z!`[‹¥¨°ßß Æ!xQ^1À—¡¸îÀWëÞº‘ù°ßÎ'Aü‘Ã@çz/óˆbãËÚèHl¾Ï=ƒ6Ûèû’Ó««lSšV;æH3¶£„ÏÎ\íÛg–ðÉɘE”ß?䫨TÃ*(§E(Hp0ÒÁÏlÍÓbªÜgΑÔ-ÿ§‚­8«4 ÉßGcó^’hj@¡Ž‘ú¤½™ô5ä[/Öwø#|_[zÐ×»UYR- ÖIò­Æ7’lW Ý1 ‘øØ@ iÆ ±²ãÒ–"~Éx¡Nݾc–Ð>f1ãÛ”–GoªdÍ£4Ñ,yúøc©‰_wŠùî_œ‰ <Êðª™fœk[ÞÁLØKã*ýäPUL¦ø½3(‰yZqmp'¯HoÅ”íW©óáÚއI;×ùõ)­éa-…ĜƙÓý1Ò]<Éâjîì@ד¨û®ÌÿNxQÇ,†e§'Yš½­§Ù)Ïi$ʤMàƒ·~•¦Òf{ÕôN3V®ò*ûÏ#+‘Q`s³8êIrg<Í™Zoå«…Hºí£‚hâK¶N:â "²CÄÐòýÕwö®ÑMð>*1Òa;­xVñ£2Žq[R¢%ýß'-«JµEš>R§Ý°“E@érË·Få¼wTŒ•;¯ž¸¡Òß…ÁÚ¤f7INR`wFÄŸt¬S}OôíÅE4@_PMŒò¶î7_DËúŠßã´y2swvÇŽ%O\eŠh'^‚Pû¥Ž¡‡Ü@¼ËÀ‘ƨ~ú RR~ endstream endobj 55 0 obj << /Length 2351 /Filter /FlateDecode >> stream xÚXYoÜÈ~ׯ  b Í&›—yÐ"ޱ¶/àÅéÑ0ËcÄòþ}êj#î†ÝÕW_U÷Û»‹×ïCå(åeQ8w'H/MDGðI»½óÕýð¥ËO—ßî~¾xwwñx¡~ÊI˜¦¼0Šœ¢¾øúÍwö@ÿÙñ½0K'šU;:Ná[9Ÿ/~¹x‹çiyžòS/S°“Ÿx* ùÀ¿]î"¹§ñR¹ýñ¿æ»i†þ?~ä¿ÃÖ/£Í?xÊã~µ[6Ã×úÓʽ÷íx_™‰>Ìs™PÖê'ÌÙ©À } _íi3¦Ù¯ƒÔK3õ;ƒ+A¹ÁJØÄ‹¢ öIHE4õîXö—»0ˆÝ²>U¦6Íe¸C>”mÃôö€_  Ìwœ‚Swà±GÔ UÞËŽyUµ8õIú‡¶ãéù8´5QØ%&§cÇÓæ{m¤]ä`å]"úÂ÷#ëðŸ¬S2ÑãmÄJÝ©Hk÷ïú9M~¬ªÌýrí‚,rÇ×QóÃõeªÜ;pì]¿eÒ1oö•á6ÏôÜ!saca.žDæJÁ\àÒ¡¯Ü{H]Ù£;Ø^:C+[ yÉoÚR7N¼$NÖïËa$×CQûD:¢fMR 婊ÈB‚`ß ‚íXŠ"MÒÛQa UH\ƒ£–pÂCiýšºéO4˜)ï+YÃ. ÃdI1ǹ߀ƒ…Iê¢Öi]’¸7¯ÉQL¬ib̓Vš¹·yFæÚ‘;A?Áê÷8ÎJ”]ë–´ƒs@x¦µP=Uô'õ@›Å€ÙkV7d±Œ#Ì:½bÊ-ÀÃÛºFС®¸ºp;6……ˆvd”1²âDþÓ– )FPb‰$öÛðÐ4³6û2$Œ´v/K|…1¡uæe±r´†ËlÅŽö ìÓ¼9(/ ! Ò‘öâ,tv!ìJ¦ˆhT¹ï/Cå~ü„Qz÷éúߨÔȽ/›=h¢ß:´Ä^F¼Ï-â¨r¡œ~êŠçõÖó`ˆ¼¾coAC­™òÒ8²0åÌâ÷*´Óì¦È*·Þ£a@A 8:ŒMa¦!ÒÇv|8 wGaóÁ4¦ËÙ²ÐýðîW»@iñ0Àfå%Iºv4]¾ÛeU1‚åLAV^q7B”‡èIê\A8&vqé¤{ZS ß™C^Nb-›¢Ä=‘cœ"Þ‹P¨tqãÍš~ÿñ»¥ëÔó“ –£À}~"DˆÔAä%Á¹6jñlÌèùÂù#~-kî5ym~:K¶æGŽ™}3³N•Å"×HõƒÕ 0YIžëÇz•q­Ø<7‡at‰VØò¦¹š7‚]”ûµ‘J臌H%¤]5UB/2Û"JxNØXƒþ)‡:0¡u7Cgò jöhìшȪ÷е5/»HÊ—»Åˆ8¼ÙQôhmu'O€GÖÍÑ#Ÿû7lßDÖ*VÞfkh¦Áì•ì´}ËŽ!B7ÀL+EÙT~-à[O)1H™}Ë À~†ÙyÚ†âgÿë=Éê‘§Öö Nu滟‹¼î°¢ bnDl,’Ñ»‡ÑV¡XˆÄ)[’Æl!¢=3©h›9¯wdf$SÝ_RÄtgg¤rFÆ€ˆ8ž§Ò÷†õÒ—{ë[¢àªÀ#ŽgªR U!×»{yމРBü©75ÁXgÁ½2‹+:µ,-µŠV¯audýŽ D ¤œI¢5ù‰ŠB@;O³oøU2ƒ&NX†ÎŒï1•Êàc öʽy©R¸'By,“^9PJ `úT¢Çp Šœg:9`$õÁØ!@]îp8ˆdÍ`Á­#ŒjŠjܳè@zH’×Y„DÕ,„Ã8ðârتˆ„sD[iOT¸‘ØcøôÒ¦¬Š%ÉnYZÀB‹¥?6¨ŒgN§=ÝÖ˜_¾:Õ¦£û¾_BœçÕh$Y£?Qå„™~ŠuètfÀ;nרt-0èÇ[ö†ñk\{ÛT·Ä 7ø]»Ë­$£Ãe ì¢**óƒ;³dÍ ï |“SFð‚g·$írwØÔ_¦¾ÉÂèYÊÝm~`_*Ú 7L5!?‹¥8i¸:b!üý£Å!ó+Ž œ³ˆ ^?9.îÎw±ó}ùLž1PÒ9Ùlð‡Ž»9쉿‚WµµàÚ!8‹%*ÛERýsœLx´$ ˆpGœŸ¬{CÝçÇk÷¾µÐܨƒ¿]m%Ç(ò Pú+åm¤’)9¬ìºÐ&@ºèZi³B¡qV0ñEªC"W;释­œèEö™D0^Ù§™À‹à6²¾R¥­cDúî \t:ŠUèå'ðÀSG—"@whÏŒKˆeÓf8K»¦"¥æ–4´ø§g3r…âH¶éö$®ÔÛ: Ü·hio‡îã›ÖÊ2¸Œd¥” ãÉZÅzÞ]°žZ†à“kž#w¶öVµ€äRªŒa¬ÕHüMkÆÞ؇4|E ãµð|ÏáÅþ sÏø®³@œµg*§}ni‰:¿¹\ñ0$$jië*@âü„•½†‹|‹ëx{f¥“¢ª%"(Ý›¢üa RÞyó¢L… -sðšGO;[7 ?óüXY[ÖQ‡€ç·/ºò4¬O(P¶#˜ÕØíû¤0'¯ eÛ½Ù|ÎàšžþÑ‹°JOeÉúUXeNìe Üù˰&œ&«§ƒÀwðU!ˆùå@'XÞÇ*²7Àdºv¥±}›I±°©í‹jŠO4ü]>‹¤‰<‹¤ò,„g‘4±ot`r ùêÖn5?ÁP7ßOo…ñ’é0†ëC6ß2€Ýˆ^ë4¤ñw…H€šþ»8^ ÏF E æåí¦L†Pïc Ð¥(·†Úý`ž¹Lï½mç€I¥`0%Їd/Vþ?í×7˜ endstream endobj 60 0 obj << /Length 1602 /Filter /FlateDecode >> stream xÚÍWßoÛ6~Ï_!¬*5'R?(­ØCÚ&CŠ5íÒ-ÐöA–h[¨,¹"Ý$Ø?¿;eK®ÐmX?èx<’Ç»ï>žŸ^Ÿü|rs–ű𮗞HKSOF1|RïºôÞû/ßvùvöñúÅÉÙõÉçîðãž`ÆYÇ^±9yÿ1ðJпðf©wk­6^”¤ð­½7'œ<Åó¢ÑyiÆâÄ“d< 鸂x˜CSeÃfÖjþüåÛs)¿v‹ƒëA"íža*¾å[È’Œy7>2J™ŒÓ±ÏN_¿!ÿB1 \…÷îý9›G<ðOµÞmÉfí„ó™þ««YÊýë«ÓKRíf[Õª£ÑN+MR^×ó"ߺQ“oöMét-}ÕértÌ›KÉ‚ ôæL_^ºDÚªBPìL‹U‘›ªÖ¼'íÖ–´Ä’V{ˆè^‚’ì7Ðè=î ÛÝjíÞ-¨e.áIŽ#çi˜±,ŒÈS9ê±ÿ{»Z9 ˜º[ÂDÓŠC9Cmƒ¶F‰S“Ô=Ô í•]¾R¤5J°E7eæW†´62°›n7ÊT¶IE5êrWÓ” nÐåîùÉ ×ncÛ ¾!6(M´KÚ«ûE¹™iœõɬ;ˆ$¤¦'—Q%Œó=íÿé0‚èí­°}Cÿb9ÉjØÅõ–›ûº›ä4xlð¬«Îg|XQrwN­TÉ0Ô¹gþ˳w$ÏbVËÄ ­ß“NŒñkÜK™epëØ…Î"/ ¥¾{L8XV PœC·mÅðº'¿Úuú—ÉgS°iv‚¿Îš|aI’†pèÒ¶|yµDxøÈ™M´Í£‡ûŠ>&7wÌÕ®!cĦ#/À°&%Rü19ŠÑú×Ðn€›Æ-maRnc[1‡É›tÖíŠÆÖáq­Nm¡%:ºÚ?Y'>zè¨ï! ˜¹3 ç•Îá‚‹ÿ”ˆåràî1Üc&âxŒë¾ $‹}§àšÀº&iAhP:ú@d»—º¤7jÓvŽ|ñNšÄº¥†1q°•=Â~ûf²g÷¼0±Áþ@ÿ íE¸ØÁZ×üÿý$WT endstream endobj 76 0 obj << /Length1 2081 /Length2 14287 /Length3 0 /Length 15540 /Filter /FlateDecode >> stream xÚõPÚÒ ã<¸†AƒîîÁƒÛàîîîÜÝÝ’àîÁÝ îð8çJÎýþ¿ê½šª™YÝ«uwïMN¬ D'hdc³±v¤c¤gàË ©32˜é˜àÉÉ•Í-Aÿ‘Ó«‚ìÌl¬¹þÁ¶é;¾ËDô߉²6Ö)'K#3€‘‹‘‹ÀÄÀÀù¢=@DßÙÌ K²±9À“ ÛØºÙ›™˜:¾ÇùÏ_¥!€‘““öos€ ÈÞÌPß «ïh ²zh¨o P²149ºý JSGG[. ÐÅÅ…^ßÊÞÆÞ„Šàbæh P9€ìAF€¿JÈé[þ]=<9@ÙÔÌá_ %cG}{à]`if²vx7q²6ÙÞ£”$eò¶ ë‘eþE ü»9FzÆÿºû·õ_ŽÌ¬ÿ6Ö74´±²Õ·v3³6›Y‚òb2ôޮ޴}k£¿ˆú–6ïöúÎúf–úï„¿S׈ ~è¿Wøïú íÍlèÌ,ÿªø—›÷6‹Z ÛXY¬àÿÊOÄÌdøÞw7à¿×ÂÚÆÅÚã?ÈØÌÚÈø¯2Œœl*ÖfvN I‘sÞEðd& G+;'d¹šÿ  ìf ú[Éø—ø½/[[€ñ{ /3cÐû¼‡ƒ¾3àhïòòø§â<##ÀÈÌÐ`21³†ÿãý] 2þ~?{3W€&Ãûø1þúü÷Ÿöû„ÙX[ºý¡ÿ}Ä@)ai%iš—ü_¥+ÀƒŽ•@ÇÄÊ`ddæ°³2¼þׂ¾Ù¿ó`øc+imlàüWºï}úOÊÎÿžÊ/à}ÉÙ¼O.@ùgеX ß¿ÿ?ûß&ÿÿ¦ü//ÿ¯ƒþ3s²´ü[Où/Âÿ^ßÊÌÒíߌ÷Éur|ßY›÷]°þ¿T5пVWÈÆÒèÿê$õßwAÐÚÄò¿m4s3s)˜9šþk\þ%WùkÑ,ͬA 6f]-:F†ÿ£{ß.C‹÷ëÃá}&ÿVÞ—çCŠZÚýµeL¬l}{{}7x†÷Qbbex0¾¯£Èõï)é­mßMïÅyŒmìáÿ:Q6VPð/Ñ¿(ô±€Â'(ú_ÄΊýAÌ äôîEæz÷"ûq€rлOùÿ"&Pñz÷©ô±€ÊÐ{Õ?è=‚Úç;ÒÿƒÞãüAïñ ÿ‹þê7Ðèý¾·ø¯£þCxOÐøá=Ac3çXü¥¶q²ÿ‡Á;Åä¿å½×¦n¶¦ïwêÆ»Ììð=¨ù?à{ö–ÿ€ïé[ýŒïéÿÃÕû½´ùìûþòüCýžíõ{ Û÷õ³ùGýïÏÐîð½åÿ¨…ñ=S‡?µþ…@Îÿ(…õîð~iý1xñ§yï«t4µý£]ïé;ºØüÃàýäœþß‹wþ|/Èådz·þG0¦w÷nÃÿYC'{û÷Gâï ì}wþƒÿ~‘@ W!üÒ¼!w y]`Ç} ¾ Ýî8ï ù®Z Ç’}§Ó#2lUu†ÿºý­`ÒPêʶ(åÀ2Ñ‹ÇqklH[—ö'ÏgÝ8Å©ÝvøÅI¬Ç‚õß ?Ð) ìy¾ØyªúY@¶‚wK‘çØ9q +ä¡ß» ˆ»Ö/û5<¿ûe¯šMá¹lš.J%R˯x–<× s‡Æ‘ŽŽí·+ÊìÍí ZöÄ‘T ¼×Is¡‡ÆSôÜûj…2“C.®!ä Úè…‡ÐA²ö‚GIQŒTpD‘1¡Î|3_'оK-q÷OÙÈÄæΡ®ŸpÊöTpŒá—-r¡¡CK¥ì.´œzöâéFÝ|x‡/]û/Xöü?,O˜BRûã-?ÞPòÃt„$/°-âæýøÎé=ý¹!þÍG n‘É ×Q³×Cßé´ ‚ýþÂkbBÜ.KóZùë)Ÿò$Á©þ0£)q67ŒÞi–Úà*´7 >püÒ¨)ióÑÚu©nwä·~¹¬cÃþež½Dˆ;å]§ÀE£2MÐTtš9—T¯5ÔˆôS8)“R^fâñ÷L!4þÑ Yp›À:öê}ý‚ä°¼Ïx-!&×Åw „\ã S¥Ó¡‡FÕBFñžS’e“gA:.¡²(Uå R‘sÆÌrfµ„üž0úÑÉ«n)z,¶…ªYBže\Ù¡’F¾@{JÜ 9ÿŸ˜YɈ[¤é|Íæ½·¦yC4)*¯.ÕoÛðÏ d±;ý“[Z›jrôÂ…”ªÓZçr{{9}-Ì‘¡gù/-uQzKeƒšïʺ¢ÝŒ•ÜJ6ç» 6>Žõëq:ÚFÿ¸UØŒ­‘s²Ÿ§’áu2-žóŸ_ÊmëU˜Ð)öÂin!‚îé™…ß¡+wW¡ûõ‰¹bßûv[¢Ð;À}÷ ÄÜl;òüæ}⦡k[V¾3η2<Ê44 žp¶Å4Vé_³iõà34îÏÅ;sÀ©z|ì¿V$„s-Tc æc !•æ²KªÎù½@Ïïæ¨½µ¦+j#5fp@kh¤ZybÛ†ÔÆú ùKjYË{[§&íž"Þæà2há¾Ë ¦ÛC-ÎC%uøÉ¼yÃ-¯ŽF§Wö €CrƒR^Þ#òûÖk\€ô ,4Tû ’òó·„<`øQñ¥JI`Û8zÔÀÒtwÚ3™íoôâI•+ÎúHE/»Æ¥WiÆJ¬6ͱ;(GV3uøŒU#]õúvÏKÙR¢ªˆ]uroUê¬Ú²t²mc5âY^KS®·²Ó]áïyùãzF̸ â?oýt v–‚€}èÈÕéîï°´¼m4#eªb؆{Ìß™kFprX|G0=Ñ…>…±lÇÜ´†‹]×OÛmôo¾•ëù‰4ÛÍõ;·X3•l,ÛˆkÒÌs>ÕüEøI–iGo”Õ¾J&æŠ+g§¾`ðq£²kÌ{ãÕ0mAVïCÉF:±1§.ŸÂQµœXAém%ôâ^ zRS ì.KB!‡;BŽF çú×â#."­„w•Nù ¸ _µ÷G´5o*(Nìdñl: Ý@š‰Ù˜oL÷±Vif{㙌`öµI¥'×ßù4ÊÏF×ø'¢Ç8¶4À­baH­@" ×Si%¡lmøq‰œEμ¦¢=ºê”?ÜbƒåîS`)9ñŠ÷±XçyòÖÔYÊ ÛYщc~#ª §ÃÔˆ~’º.ïjFÕZœÕVÏÅÀiKþÔP•þ¼dIÝ2;ŠÏõ• ‘ŽÀvˆý6©E¦í©áç¢FÖOaïúŸ–77áhíF©Œc\@¿G€ 1-ÆOøÎ¯¨\ä/ã4¿a9™U=]I_¢,çÅ«›¶ØÁˆ¹‰ ÀÝìh6÷Ê/¦¥’|¡a>ì9ß™í'ç–34P©XjŒçiämÕuC½¬Éš1Šd<¦9Âk.)DO, ‚è‰.¦Ý>Ìf¢^þš(…V'îwIŠ˜÷d„3Ïš¢9,èA¶îŠ@µ‡Cdºí~%úº’Ð{ V¦ e ãËÏ-¾ûšvéÍÅpô™ó N*yw„'e»¿h§>¸Ð‘аԓ­òM·¤ð’V¤©Õ :Dê¡t‡è¤:"Žç‡ä_iÅü.5 IŽ­‹ˆàs•;-Í[³ÝŽq€,Êl—ñ]’/4å»Êž±‰ºž9Î)ÉÄë[–âþ-E£e?ND …ûĆ3Üg‹=oåÇI#‡Ð™îÕìü 80esñD1äá]«röJEQ.\‡›¦÷t\øvb,ýƒæº’‘د2ª8AÉú¡àû¶7i”îGê`m¬F-³ßĘRcfÃv#)VRéz€qgN¨µÒ8²×m˜™¸*›‹~38ö&™U]°3ª»Æ|™¹}¹#E»´[â_ÔìCN2òã¼>cÞgϺ«R^„ý%ùyX/ ¡”ÝŠN½œdô’e}˺Hس¤»f ÏîöÛ/w‚W9Üä——±ž9ÎzTŸúèE‚ ˜s—ö’¤É’p1ò>¤vh™}êÒ’§Wú3E°Û7fß û”‘š|G kaË™NâÈýžÝD´d>*qJ,þþÕ1—io|-^¬ó¬ÅÊ’Dº½äŒ©ôu¢ sKzG©P‡ ÁÛº5µROý‰–ƒ"Ÿ]é‡Ùë·Õ$G šß¢ÛD·O÷N1ÜUKËiª%Þ1° 5‘#¾v<ÐѲFºíRžY E@!^æÍ Ƴâ–Ôš„­[: Y†HA}dÝݹ([#ØpúÎëÍ[fQÚXž eµÊok@)7Û [M×zë´÷ÉŽ¼tBT,ou‹T¶°Äâkû¼Q'q:ƒ¸Æ9åO—HõÐýäT ßãDƒaÙ`t³ÃÒxØâ^j(ã’€u¯,£É]á<Ž÷´ɯ&w!‹I݆T#mv~&c|e,6 ,æGÈM´AÕÕ#ÎYAÚ:rÔ¾q÷×êÄN‡®XKT¦Ú³cÉ>–$cÍ¥/ˆ¹ø žƒX?Gk_ú4hô(Œ}²^Xh*²¯æTˆÕB—IøL‰ÿ~ÂócYÄʳ¸W¡28îþç´åÜëÒA>ˆ˜éœùÏ9té-P¾k¾+b÷].²òʱÕ"R)#_ðÛ{<`?<ùu*¯u5_3U©âÆUÉ9¬OG?]¢øt‘ ,›F^þ"#X Ý¼âËÞ Á»²9”þ¶L"‘9Q<‹’h)gB-Qcÿ,UKÙtÞNø3}ê²ÒQAr5vóŽÞ2çË,¸ù¹yv‰B<ãY»»ÓPU­šïš,•ts`ëŸÆ´$+@fïüjî§Ûdö< {o%ïˆ Ý¾"¹oøÞ†u2”P€õø› ÃaŸi†¢gM¶ò<¢G,eEÊo²õ X®‘kÓn¼»·›Ù7óž}Ø’lÄEüòX1lÕÀ·åPñ­Açf~=%®c.)­âѦ!”{Ÿ-Îôr°Èœ‘Už¯wšÖƒßš*¯®ADÃaÌltmÎp‘=v“’€à&yÑæ,/Œ×Œs“c"³GªÐJý\ðE9‹o&ÈäÚ—yò^JÞBIÌÕ¡ÛÕ _díñD«N2çdžIˆO¨qhÒ‰ÁUÃâ&†!iù™Ñz¶]Ù“/ØHñ»ßô‰¯ÂyC·IÑŸ^†’†œ ±# òZ€ ëâÝõ+¤ …;­R-=ƒÍí9²[{Þ.ª1þX`Þg4Oº º êÑñ{}ké6ŽPÓ¶¢$ µ¾SŸG•}›‚Ðõ#£É^ñq…]ŠEorðI$@ƒ±#8ªºcUBó¼*mGL²MÉY`:ßì°ÉeÚôÅ(í ¢oä<•ÜaxÝ;] ôv?£M}¾ ϵ{©ÏÔVÀ?…¾²â”³»-ž=Ÿ'PÇõ#ײâñ»ƒþÇÁR—xÛ´j¸qûµÔÇŽÜ•®ãÂQIp½Ö³h:þ³mnº«c,q/%²Oúžˆw›6ˆ MNŸÏ]ÒQ_ª¿¹ù‰¥®Ùö70}ÂhMð’¤^kÀžàsãO“ׇî`ù†ö̵•Tk ºŸ£ªÈØ4­úûÁ€6€$DÚFŒÁÈ V¯í÷m4{͘E\g´Â"žÒc¿Œk.µñuM›$Õ¼h€—4bè7ÇY›ýÓ¦ Ÿ±é©y˜.Ž æҎFÍ÷땼¦_O¥Bܦ‚ÃçšvÂ7çͱ?”¬Õ{»§ËxØ j)N›’QEp¹Ë)Iɬº˜ëd $þŒ'lýAð‰jZyÒ{RZRóQ:ÆFJË›’Ï›s‹¢¿p͹wKç.º‹ª3DuŸ×RnÚ__u±®”<ŠzkÞ†qÅęߗ…­žÝOâ6ë˜øõªQîú¥×„%_Óó~å¦áv~p4 ÐR(gÊÒ=èŽn/¡K:C ]ͰÝ>fý0( ;’ß§O•ÖÈ\‹Œ»¨Â‘@Y±‡C–£WäħeR&Ûá«G˜H) Â}€ˆ‡~©–9w3™u!ªÑpöç±1iQÄä϶ »ˆú3ŸnWt…?bƒ3Î!#??닊"¯°tñh UxA³û²“/¶¥îûZ™$›,Â>W»@ðŒ %¡Ýzþäþº‡PÕmÙ#æ±XF‹y›±WÈ þ™–/Àò˜ _ÃÎN F+ C8¢æŒ™ wÙóR÷ N“ég©Ç}ËèîžÇµn=Aøûp[fvhöPÞ¤¬ˆVlÅfP4HÓ38RUÆ¢ÿ¾™›½bO‚‰¶œ²N“uÙUçÉ@ðBê¾Ïmù½æ‚ÃDÚ>Ìå92ÙÁ¶–»À"ñPS8kaá-&]hu={‘æ\Vm@Û§™æZæï·9ˆú5H 9eÞ@»¹çó#ó—^¡ »pŒ·:î^J—"©øŽ ê€£v¸ÈšRWñ‡yß-j?§uè_î×;Ø5þ)5øÇåö_§N‹êäÂk²›È¯¦pMàÀ.ñTÔ)LÇBÙbå»ö¯7fÕÆ™ju–qîcÁ‘ÝÅ«OŸfr9Óãå//nƺJo$K|Oô&z·xBlâûð/ƒÇBIŸžÔÏb1n¢[ÕE½Àj3Nƒ‚ö@jhíºÙ––_JÑÙ^`ÌlJýâÅxêcñ˜gSŸ5 _W·äȱ־À踌ã¬Dô{¤SˆVFråYðPÂñ/Ò„Jj›%= “à³½ç–Ó«¥KÍ,\ 1gî½V-„æÇ¥zo«S xÅ|ºBŸæmûv‰Úc‡äå°ågâÝŠ2z(í×^mì<â&LSªQ@¿gº±¦f™åJ0ó/¿aÍõ÷Èߘâó€¯/ÅíÉ´FS!ZWÝl6Q)§Õ³‹=­x¢}`âsš¨ÓèÈÆ Ån¾ìêš9ˆ¨à°‡FhjŸÙÚ¥KžÄo¤€çdÞ„ÑÄ [^9HÛ¾P²Òõ‚Í\·9¸]½Hqq6^£Ub_r׸"”"±šL•`±Æ÷–[_ÒTòÍêÁ9Êq–ÏØ´uîKŽöwT$8¡Q§)òô®_n5‘œsÑC{§ÞÃQT>/5*H“Á—ã¬÷æ¥ÑïÔÏ>.·S6À¿ÁwCϼÙs–™¶L înå[wN“#H{󬌸¦l9¹éË‘^|1Äæ˜´~ KÖÔ-òï«l{u SÑì•5Ú?=þÒ•úºfÜ;Ù赺J:‚L¡} ÛÆNÝÌwó¼¥#Û7íö$nÔz#CPÌF\GþIzÍv#Ž6mÛÚ¶듌·š§Ã°‘š8[U#¬A9¬: ´´xaéÀûÔ>ó=*j ‰5Ò¸`²ÔÕ>LÒ&&7½7xŒˆôøÈŠ¿FÑ$w¾‹ëUÇ1Vñs`ŸÐ*©o¸ûþ7ÑFÇs, algmxæÙ¹ß4:lw‹w¦Yß»ˆ”|$7d”[аý™ÜüéLáÐaËf«éë¡Bµ ªœí¹;7Yîk·ÚÜcbñÛåw2[­P;&™³í(iä ™J®#S®©ŽÓµ1žÂ’#XS ÀQ¨d ,ýÒdu4-1[|Çâƒúõw°º ˆ`ò¼€{¿Ô±a‡\,·$BaU^Д‰MJÎŽ{I—ßuT­Êôwɫε«[éè´å‚1æÏ›b‘Ô8mMúµ­dr(^*NÁ §|ôòu²ÙU>g ‡Ù†ˆûyß=˜ú03lÎü¦PôD&äî}Ûóœ"º(v"°Ã„Õ¨$”ó+žvǵÁŒ=&¿^zÓP…Ð^‰(ôÏ%"SÏ!O–0Ö¦áÄWR×+Fû8·ùaI☆û~==ñRÎ".`l¢’^P Gâ“Ű:žJ±w…êÀ¹Øª½{è ô ÿ}⤋Œj[7¥Iˆ ßØÉšï­Ç|ÌÈg»~ª\iþdd£<þó(•bQ{£NJsðµfUóÀWàg7©‡ÙöÎô&ž„Hð@—)XM.]±es§P®QFº3ú9ߎP)l,“íæ'Ml¬+óÙÍ_b[Jñc6%!cú™Ó/᜹$ŒÍs+Ùéz’ùÂÁ$œ<‰‚ò·R®Ž 3Y¤w¨ñ(–#nÞCÚô™²Ýl®x‹ÙgEE,RU]AS[÷Ù.‰`Åùš!ûê\Åh š‚üݰá7®;·ÓÖbî®lî_°/%š’Ãùɾʞp×Ùlš?eëgóþJ%‘gO<h2 vfôŠ9rªýyÄÂn¿R«*B×¼k)ãÏñÝmi!§ X@¥ß<Ç[»%³þ Šš}T³šz%ÎýbáŸ!4›â˜¸òÿÁ[0's+0Kqe>H]™˜ºÞªÈL‰¦–áa1Qãx’é^CFNJ<ŧˆ™Çká¯ÉçÄÙ2Yþ,%Ác[O33*Q¡pÖˆ†¸ ÓÌ6j²FZ1]Zªõ¤Å§?ch¤-áý ÀI'âTœŸ–©Íâ,å6w‚“ê¼™ ‘uË¿I}gjp< †u_uBþUÜ T«£Ë¡\¾ûè&ЍøsŽÊF!ÀBi—Ò:B”1ù2Gs‘ÈFLë^œQÑR©ÊøQºfUÞ û›Äá'Ú x›”aJ”Ÿo vó߇|¯ø—;IÔbL¦ÐBóÍÀMŽBÆa12¤‹pÕIâþ²Bøb8ëÌõÛ3Eò‰/§I…¨ýíÖ»tiÄúŽçø+ZÏ¥oŽâc7ÞÒúXÿ5püsÀlm+¥¬¯§$ýtöÊOä„>LôÌE~ʉ{ÓìOÏòß›Qˆ£xýÃQÚæ¸Ì'šœbkl1ßÑ;òiÌ[CÜæ©úSÔ %‡7pä¹›`”ò>±™ [ái ‡Qëè}T· u ^b@ÜdMŸRÂm™-.Þ]õ¤q(Ò›ùÝØþ6‘7Ñ”æ½ðP P÷<‚ÓRZ6[æÌiÇó°6]ÃÚŠýVAW>uæúty8±›é’+ ©qyéáÚ -HþÒþøòA0ZÃÈÄæ"ª”<}É9ý+GÀ|f[gŸ:Ê êüF—qÁ®afhI(ü-#¾*ÏÙra¶ù,\ÁS‚Ùl-ƒr9^ïNnq ¨²ÍÔ  Ú«½Pò c^Ã<Þ›q.¶µÁüÔ2K.pÑ€ ÉwpÔJL<ƒ£Òzt[4·Ã}¿ob;³™ü0má"—Þpü&µt‘.óQãyŠ6]­[6: , Nƒ?Û˜õ%†Åv·wÊYÉ:¯ÚÓmâòÎG'…ðõ‡€“f§«,ØÇ·‘à™…cóð¤ú¡Ì4#ôO`¶ˆA|BÔŠD^ßÂÎ)=¾¶ù·q.jÀ…¯C%â,› –8ôµAyòú´ŽÜ@7à¢]ÇnÅ=.íFÜáW·ñ­a>ÀCzo._[ÇÓ7ÄøR¼áÙÚqÆÍšfØ ¥£Ñ%ŸtŠ'ZuíÞÚý\ÿ-ïÔæ.I#õ³Üb&•˜°±hÞà䢒hÐI¼¡Q—¿Qй÷4œ±ôœkC-:»•OˆÚbXT’bÙøF&ùâäkç‚„íwï\½•q>„ÛktŽék¹Èp‡ãÞÿ»[} ЇÆ{¶éÍ”ÙÐʼf4êzgç{ŒC,‡sÀw>×,žFQªR¶Ï¡aNI>¾I¤×;#4$Lrö;½o7ÜY,§/n®KòÆò†eü!GŠCCÆIêS})y‚l€Å3ëÒ¬„íqT¥Eî%+‹˜‰ ?Üg]ˆ °áX²ˆ¦ö <˜] ÿ0 è ùMQoÁƒÑ¿¦I÷Ø)öÃ~Ž[tfŒô+üFQ'±ßGCe^J†5“¼˜X£9oÍš"«oŒ½JlMuІb±ljKæHš$¦Ì47SVéài³L؃ƒZ4R(F ïRµ4‰pŽý¯}çªÐjUgàã Ðø5 rf¿Vm¦É`$ “$=ˆR ~ÛòùL¼{0$ËŠò „Íêí±±ƒAY°=SÃai)´¹Çà\p-üÈ™•pI×êü•i¬äÛG:³O*ˆDä\“ä˜i_ŽÑ5¸×Èêõ›å˜ð<%Ukõå‘öæKÕ7ÊšæáÊ ||ÄLgµnŠVݪC&‚Ž_¥øIB<ö4,k³Ôov;,.®p”Ü›pù Ž_5Ñ&}pÙ@„eÄ(=ÂYì¶ø¢êNuûºto–O7òhå’e„¥¶ŽÛXYàºlÞÉÊVë{‹k¡Ìo‹ñß²TÊLÉsª’Õ©w=o`ïb‡Ò—ÇI²¤3o'Ǻ’5„Ð++eÓÇ祢Ҫù:årÊ5¿2L&“£³$¶®}EÑ“õ½‰üÜ-L%²š…Ý‹^Fʬïš5l÷̙魤£³üQoÈ•@kR:ø*Qì×d»æ³“ˆ|Gj9$€'áñ(+z€Sé¨мî¾Gý𠜙ú Õv‰ ¸Ðœjzaö§ÃÉÌŽV¯Ø3UòLJU ’锉µË'žSŸˆÛ½VŽB$õÚèi¼ô„W|ÕÍ«ãÅy~#ß¾¡½žµ·bì¯Løäþx ¿ejàUúšê ôíž[ëúÆÌ`dž›ßÙ.HäY¿ýѨ¥ª ­ÇÖ囿}0—4Ò¥#ÛPw¬¦!ÿXŒ4c.¢(ó] ÁË@kßo¢Â£·9.’VæªtGsÜãÕð ùŸÏ§‘0üÜÒ°|™/:¶xbÇšW“«¯$á–KÓ¿ˆ¨YÏ­*†Þ¦à'„è—ë-=Ü;[°eÍ€opM}Ãf$ÆX¥ó£ÃKìßâ#OÑÛó­lÛ»OíËûiÇÆy)3›}F’”]p ZÞ@¥Ku±©6=Ïæ»?ÑHµÁðdldÂGº²ü U¹‰ÇDÑäXsVq ßï¢ áxȆTÚÈãÏ®3AÐàöx”òãçÒ }4N:Ÿ<³©à£ý×£¹¸W<øš,>ؘbÖVo, f´_/¾pÎ;X0åZÐW¾±­½Ààt>²×Ïá› ´‡„;êÔ«cNur]È }WQ.EúÍÏ0€¾Wõ’/ïÌÊ@Šb)\Uô%iqø’x¤Ñ‹“76àa"rŒBd¥þ)¬ÌQå…<óH¿ ¼.sÚ¼ Ê‚ù^ý“BA÷ù Y„ÃRº$Ê ŸÝ³Ø%4ß(7|~8F}Ac H§ÝàyÛÿ"0Ô÷IÓ6™T~’qÄÛp¡L?¾ 3`Ž ®N΋kZ«Ç¢–ˇª¤/ûº^*á2™ÿQÝ]ílÝCì·:Þ1"$6œ¼PòàòG}•‡P¸¢XË&ÜŒO¹^R+ø)ÞdFö|T’Ð+´'Kß“ÙÈ:#ö”W‚$¯ LôµÃsºµ4›Ò"bO9‚MóZ"Y±—a¼ÛĽ„ —–ê–vÿ†Ç*ŽItùý’ÄÎFòñ”2múòôãD$¢ùt$U$xP›Õ}Ad¨üy2)79È,ütè¡<$o©”~ ¸|4ª’BYYÉôô©k¯nl[£ÐÚéë*Ê«[b;m—Y|e©mDÖOk²®5jì*ŽNXùjþS M ¹Oˆ$Åqÿ)@40fN¢!æökÓ™ZYó‹™!‹¬VåopoβE!ßÒ‘ ±æòVŸIÉËÖ†/(¦g‚˜_Òêrh“¿/žÈb XuÛŸÑØ`Å«ýT7 ­-dü¦‘2w”Þ»Ñ1RÓÊ:A’fpΊۭ*‡*¾aŠÊøk×?ZïÚ™±XxXKLTP§ÇÖyÙ^)ªQ™~ÿZ— ‰° l¯;Ùën¨“}*hñj¿†*¡OØg ’£Í J)9rgeã"7ür0§K^ª¿ƒÌêî†ÑfQžŽ®êFaϱŒ_'ØiõçW—‹}˜»0P09™¾|,6Íl-l¶D8ã"Éȼy ûd˜=SÍ3,%~!< }©…Ä1 Ô§GVÔ%Z®Ÿ½!³IÅ)!xå͇$úVµÜ®l¬žU$wny·cÀ¢3ˆ½]VKŒ%Ër”òtCÚe*†Éq›.‹vÊjC­ŠGs|8áeÆós7"É*Ü5j‡èXW5&‚ÝëÜÅ1ç|@hÖ‰¦Ô3þ¢Û\¯7¾œ#7Ô(!i:ÕM7°ÃY‹þ!Û¦LOzKþ¹sGæ[Ÿð¬…Åp/å4Þà¢é¾Œ}ˆDÆ Ô7ì•”µº‰)ßg¶&fÄRÆ)ÇÝïtÈ€ÞªVô;|`üEf…)9=¨ø•l×kºø7 A½T•F\"Þa¡@ägqµNcbÅúCE¬a FœñTAhã¶ @¬E×3?#½Ýèn[–%X‚>NXnÇñèWVŽ;˜Þ-º"âDx yÄ8ÂŽIuGY’HàÅ)±©ã6üØÍ|ÐJ40¾Ã[‡¨D>u Sõé’ŽÚ&GCwMñ[¾“î¯ez¡ õÂÍvum<Íã‡HÖ0;º-*l»:Kíe½ÏPБ‘™ìµ^òÈ.\`œå8èŽñäÑü±,ùíÖ[á%·÷ºíSùâµEzÞa ì=t?B®ªàïï•mÖ ù›³Nꈳ®ôÄæ‚GUUû€¼„”Kl‘š×§+òb†¿J0Ú°3„)˜TvÚá40%ñÎSzè*Ñ“Œa|Ÿ‚õ-ÛR¼ ŠÏ¸ D›Wɰ±n¶©,ÞT²Æ2áW³æ’Ä\ó uÜ?5EºWÏç6A1VŠb©ë‰XŠ‡Ô˜Ðà趨½×¶íf>¦—”DRŒ«• îßÁbΖë—Úœ\_" -Ëÿ>4>àýÑöW•i¨âÕwÁjòÇÕ ZBtœ´ ØC"OŽ“§gF)8:¨ùÞÜš°¤ö/¢˜v Œ`º‰!øœOc•~æu ùÍ­CgËûEãCËÔÕ bÇ_ìÌ¢]øåâzéA›/ÉZå­ÖëXÖ^ë}o8«h¶ŸGJzädmv"Šã²«PcXätŒ^° xèÏè*o—•É$×´`zP~ÌI¯ d–‡ïdÆ¥{ŽªˆšºVù 5¯ÀnJ+ €P6Õs»q7 .vÌÈÉÔz+i¢ãå.=áŽi'L–ëA/a! w×\|0¾cL*‡è¾˜÷WJöØè ™ÚüüÑ<¯6¥ËÒ9 Ž·º[óòþGÔ#Ç3f÷¤÷œÑXEQÚ æE]tF)¨ŠKÔköŽ n*ˆ­÷+Jº ¡ì©é$*÷3Ödö¤é‡U[[duŸù Ôò;ñ°ÇÓðœü5K¨¶9: @/—rèJ@į—è—m«W¥,cb9 W§–Fm…ÁÞU±³7`ÝnG¤¥ÄxìMÚ’wtQ Lš®£;]°´¬`«Ë^¾z@GÞ¥°z’ã+fé×’ÈãËjA²~¢Ÿs|!ƒº³ÔÝÏÊ„QFÊX¼YœÕKÜY´3²ÆG9 %j=¼Éå×Ñë•>ðoúŠÝš‰hÑLÕ·ž.lX2ônµlèß´µoLñrÌ1ŠE1Åkʹ¬?Îl'‰@±5‘\·æÁ÷o•sc»IÝvGZêK]éÊÀ±Ã€Å°òë‹ð9«Z¥4êÕ¨w¹ˆ4Ï<¦¸‚e~6+¨[§Lº3øÒbË¿˜Ó ¿ƒ ¢u©l™ª‘T/$ÍæŸP-hßk–?9¡—¥öžÉ4»Ÿ+ì~´¹=³÷ó#Á͇@mfe>Åô›iûPù Zµjý¬²¿ååí1Ï׿žLµ¨uÆM4×hƒ‹=ùÍ Ou˜¿¼ÇY¸‹S‡«úpy•ø—@¼D»¬žnTþÌôŠ@;|É.ç[º..ʤ¯ÕJíw rÌG=O2|ny„†l§h¿½U_Ö8È'Ó­æÍ4ôvËt×à_4õ !D£ŽûtˆM¹¨ÉJÛÖ(EGæû$¿I„påGj¨PþðRà:^ã?èYráÃÒÃOs'à”™lã}™üþy4P0ÞÕNØåé!@å³”~yf¾%+›ÑÆu4s(¤§^Où¸y9EKöR0©ÊNÀbÔ±.½iœi„ÅwSø]XØZÑýc3D ]@,­e0iÁê¼*c˜G3 <#—¯:dÐD¢‹âÊ?¸ ýúœà§7ÑJú|>Õ᳿O;á+ä\)ƒ“W«“É„[êºÔH>€åÉÎW1m“™E¦ék§'7h…]”ãwGϸæÚyU\deÕE:¥äŽu³XX”§._ÌdFV¡ê²;Ô²8…~Í#ÓLã™I¨Óy]+1ÂM§²<„á©'B¢ÝÝvöDÕ›Ð64õÐÑùé`IÒ‰ãy…Vn¤Ê"ØØH>>§KØ®²‹8i%$y´ìkØç9)#ÌB¾Ó}©ûo„ð;σŽñ¬‚ÍÕÞíßíµFk÷l]ý`Š[çÉ —é/âc`‡Ëþ«;Ú¨ƒ¯Ÿ¢ÛüØJqÜÔYÁwn¿šà}…ê|¿SÙ¢m4SWq¯Å|›!Ä=LÁۥ׊¾á»'éTñ¿vLêN‹¯öN?÷àíº%÷ü{j¼XÛ|¬äãÙûó­õ²ƒ4œ!sBÖãÃ5ÓÃòš.(“©/«¢ˆmBJB­B„î&úø¤Ä†ü.'9ììÏ/‹·'ÒƒÔ›¨¤€H¿¹êöp<Ñæ¢ŽKµ¬Ì‚ºV8TCŒj2t8¹ã‚u‹ùñ0øâEaK ø›ð$_ý„)âÙæÏÇq½ÆØE¤WìþX E—8 ‰^Š8•çÿ‘8 «j3ØH÷2Å,ªÑ ןX´Sœµ#©9§g®AcÅegÛÕÕ{D‡A¯bÆD“²Ÿ]Íx£“wñsµ=ª—°cxï‘QîÔGᬀVç(°7ãç±Ñ‰Ìgu¡„ƒXvNÞb›Ã̃OÍ„D*?QWj¤r—€¿®³·h/ ¬¯)Wz„û[2^„*± Ùžjý´Üä‡o¸:ŠšÔDŽsÙåê.‚k]Æ…,*oªÐ30ŠK|^uu·alTŽ,¶ß’ãw´.µL¾72\ÖÌ3SÀRp„àŸ‡?ùÙ$š=lË£ÍúÄ0Jã “ëÇ©SƒH­Ð?dÏø»×oae&Eƒ©D‡78ƒÌ³ì«ŸhÖµÃl˜¦Ñ÷„&P¬B ÷åÓ-ñœŸ†˜.w“pÛIÏÖ_%~•bMyå‹J„ÖÐÊU(Õ¤uYt¼ÈÚÎÏè/Áª/ ²a??¤j(Óô)q{[ˆò®4>3æ1çxt8÷”ò õÿŒi›‹×ú^„’B'Ïo¢Sòy‘AÈѹŠ+¸Æ43¤ÄÅŠ…¨î¿O0‘÷òÅþÁ¢ºí7Jû/Ìã9ž¾z|. ¦ ®cLx–ºPBÉ$;8Ó5LÇòX·–ñ!F5WC™ò\æ¡âàX/ÊNŸ²3#”³©Ë÷ãøÓoÚ€A°6)OáÞ‡öøþr“hpõ¯[¶º3`óGöppy±Q¬ŠåðBÇ_¶bž[èÈËxâÞÿ}fÀ̺ˆ'Ô…ÕJûiùVqRùWa=‘l \|ioò\ùä Êo×ÐÞòRÁLœÙÕál–ƒPâaÉ:» +s>¾5þÝ–¤±ÏÁ¶¿œ’'·LyÐ#Ååì1¬Üøöyk–ç÷BtaõõNÂÚð®YäBÂYêO·gA¹û(v` ÙxÉŒ 7¸&Ç#\K\%9.ˆ¯W¨FmŠ-|ò"ßFÍBÉ´vWUSúTh#äPãó´æ6TVäådàV"ͼpJË1óªû·¾èœV”œcË+2ß”@¯¯áQ¥“C>ç[ßµ‚¾b|G› ¢íbÇÊ|¹™Sªòiµˆâ4áÚgí9¿)·æ§ðäßÞ­Vp„qÎŽTY¢Úÿê“×4…¯ñ–wØÄÏkBîµÜq6Ú“Î1I3Kœ‰µÈ!ëWÀÜ‚”–üj|¤ðºÛ¿Ø§ñoôù‹Ý;Ûxm¡fW鵕A,Évê[IBƒ[¾YˆfF(Ÿámا ~UNÁ@l1tã®tïDÉ,oÃ`Â@JfŒ¡5_õ—´aAA+¾J­kÖ¬À‹­ ¶i;ó Ì 8m¬°@÷¯AJf“ Î:¼‰ø~̾lÍN»\.Qðö,ˆ°¶ÏÇÔ¶ÙÆ ³ …þÛž­PéAíö¤¨mt·{èQn&>=`âô÷mÕåeñ¨)âiÝØÌH»ì½ ÕÍýäíç¥TJ#˜ø@þ«ª7‚©ŠÑùˆ¼%ˆðúëC æ:IŸÒÕï …$ÅgU,_˜ðÏ´9:Á2)Œª¶Lì.‘rÙò^¥i€\’郦äÎèd½jÅd7~ aõ­sR]¡ãÝp㑹P²¡)SÃ<„Æ+ŽæŒ^4`D‹!éúLšÆWÖ2¶ééºQƒD¶=-g{_(›©Ïë‘“õòˆs&*FFåJMXh•r½íƒ@ÛçÅrÓ¨­ÕžUŽŠO)\ m®(OŽDëN¯<¯l™b«މ"½ùLòþŒ«@;¯:4l~ïÄ]ÈdöØÉ|óJii“ARé!›Z²,¬?ÿÕb/˜âÎ/j»þz’Xþ ¥°£ð³ÒsUÅ[äBóË@-õRùnÇïUDÌ›²Ž‹mŽyEés'©Š,ób|$XEŒŠ|§E'cUXddÉ rݹ¶bô’¯HÄ#Ýô?IñŒƒâºp—3Û9ih¿9ëlÜò ~ˆ?jÈeá~¸àÂê>s9$Úù¹Ð{¢cé©›N8¹”{ËŸ0Y›G¯¿Ì¦{ßwuS¼ljÉ/õ¥¬*öbÎqbYÕÁ’霰ë ”Í";Œ8èÅÑUo4Œ,YyÌ‹ÀjweTµcY8;ëC]"Ï»r÷ɹü|«CÕxÉó‰ ÀÖ¿b -m4 é˜7õ|µòt°ÜgÉÐØ°x{ Ú»ÅJwóôÀrÈ­B¾ Å›õa”"n¨EÂñ‚hè¶…Ò×ßÌÏYÄTšŠþfGÏvƒ“lÝKi¦.¯¼¨ƒÍ3ýÀƒýÚK‚1~ÁIhÿ ®fh‡\m-Ëe‚ðkKâ´õ/B¤Ð¬lYàcíJðÌäþ9Y³+·þ*¡l†”tð$,Ãq†RÙ ~]¼±näŽÁ<ö=éh­ JÃáÍîSHºqâND™¼feœpƒÈ‹ ]¢¦|lEDa£ÜºÝo—³éâõ±ù™Û¼'£* Éñð ?OÚ¼¾œ¬/ç#Ú:Î7%XI¥«÷Øv â’á‘9æñm˜,÷%Œ€1Ål|ü¨P+L•&þ¼’ÐYkhº+zƒ”®y˜ä5Ôy‹ Å,K^‰ ¨ÑÉYÛð"³D·ÆõN°âz¿ÁJï}i™tæ?ZBa4¬Iûø8•b¶=9XP¼B~¶¤‘1ã´©øÉe© 'Ù"0Ì©v+øË‘˜½æwjÅŠi#wKÌi¼u”+fõ׉{Ší»©“Ê«Øè…ýèó»:~ÈSjú,î¥qT¤·úæÊmsÚ¡ò×ý®‹9ÍÊMÜÈoæéuZ·S½¥ΔÄ,{T!d¦…EtŠ‚I9qU»®!'“¤§ÙDxbéK7s3ínÄ/+Zq¯6›áñ-"_¡¦Òq8Ó|¯=»ÂU‹×Äýk¹m»vk|@%p˜/Ÿ¬ˆd +T@Ç#ó饬‹Þ-tÝéÌ¢¥¥p¢o¥?˜uXåÆ6ýŽË3‰?²6,Ýz’þâ5슻ƥ âÂã3õ¼½p6ón«Ô‘‚¸ŠQªYN‰f È\Q÷¾ûêo%Ud¹u©îÏxÙ ø¶\ôü Ôf9"KÒž‡þ| ãñrN¶6¶ä§uœ+ÔQlâñRáàq£ò<õqïÞ¢I3ZÈ0¶N§TÞî!8y&Koc›í•à À˜”2H¹Ó€²½Cª‘#\†md¹oWù<äR!#;²“úiù¬$ ìÙ¤q4d*tØ|uç°ó|˜&Ž&óIigrv Uª¬™ÓáF©0@%è¤1Pb¤‰DvîÕ"~‡+:)›í©272³v‹Öìd;k›‹ÂÕÕ-ì7<›* ÈáQÚ«Tk~d6ÞYGdœºm§¹Çñ¹áYÂl¶¦;îó3Ä÷WG˜d†µõ¾$i°-ó ëÏ:|ÿê|h áŸ3ÅP»aæ*È@Ü'Y5˜U€‘ §™?¿Ì²æ”(É>BÁŸP3«W\¡iŸS"º†Ê.× Çø¤yÌîyN´ó+?Lzþ—…M&¢“;Ù+«þgùt0ÖÓßE};Ju2”¡I)óB#: 1Œß.Î!Â…Em¡WŠjßY„9Zdt»>ëÊ^™­=Ùx íéZ\2Õ³÷sôõ†«Z÷cØá_ð«¤hÝ"ùÔáÊé—)GùQT¼Y+i”™i‘×ÉP½XlNKúUD£ äáüÚÐÈznÓ5Årn²ù¾ #÷£Y‡)ñi΢ ­/eI[UÆK®Þž´ {1˜êò]`ø1Ò2ÍO<Æ |h«ÛÇ«ëT]Æ7ÿ^"ž×dñu8»Kp•u}[D¹ÝâQwnìˆNW_Ó»`uöÿŒê\Ì endstream endobj 78 0 obj << /Length1 1453 /Length2 7143 /Length3 0 /Length 8122 /Filter /FlateDecode >> stream xÚ´T”]6LH£4ˆ ¥4CwK H‡€Ã03À38 C+HwI#H#!Hww¨´”€ˆÒå7>õ¾Ïûÿk}ßšµî9×Þ×Þgïs®}¸Øô”¡H[˜:ÊTuUT… PT!åâ2†£aÿ8H¹La(78!ó_U ŒÆÚ€ÑX¦.Ðvw‹„%d„%e€@€(ý7‰’<càP€® @‰€¹‘r©"]½Pp{4v£¿—n@XZZ’ÿp€² ‡€]0Úæ‚Ýv!!pÚë_)¸åÐhW!!A°‹› e¯ÀÃð€£†07 ƒ~7 лÀþîM” `ìwûÓc„´C{€Q0Öà ‡ÀnØw†`·ié¹Â’uþ$ðþ:€° ð?éþŠþŽø# ]\Á/8Â`w†©ë¢=Ñü0ú›vvCbãÁ0Ül‹%üQ; ®lc[ü«A7 îŠvtƒ;ÿnRèwì9«! ªHíFú»¾p ‚=x/¡¿ï× ô@øüíà¨ÝïF î®B&øSw˜Öƒ¿HXélö04@(%)Àž`ž¡ß[{¹Âþp ÿ6c»ðóqEºì°Àüàv0ì© Qî0?Ÿÿvü‘  p` ³‡#Hÿ“k†Ùý‰±@Á=–@¬…Àß¿VÖX‘A‘g¯ÿÐÿ¸e!UC#mu¾¿{þÇ«¢‚ôø‹DÄa ¤$@»ðûw}0ü¯:þ+T a‡üÎõ»^ìAý]3æ/pÿ5$<€'ÓCbÕ pÿGìV@q ûþ–ü!ÿJÿåÿ.öÿ-IÝÝÙù÷_Œÿìwöú‹‚•¯;; ºHì@ þ—jûs€uaP¸»ËÿzµÐ`ìH(#ìÿ9K¸›:ÜÕ‡£!jæO»Éïys†#`úH7øï' þ;d'ì3â†æŸ.°vâÐÜâo ÃÎÔ¿KPC@ÐßÃ'".£P`/RìÍc‘8VØ)…Â<ÿ6@HDcCØvývHéï[Æ*DH÷·é$…Efÿ i,ÿƒ„…EB®ÿÅB¨?à¿ ‚¸£PØŠÿ¶Ú¿ñO æ ƒÎÏ !²ÁŽÕÁͧUÊLë#rû©§æ"#OˆÑÝj •x£ÌW–¨Ïw «?qlÕSyzšµ8ûÓçK k­—ر«ú–=«mì̯cÜ©Ÿ“»ì3 8¹fÉ*,2E¨n}æÊ6E¨}·…ïýêι{´oÔ%µCšõZÚªÞ¼Ò¡¿+mº»jˆ~oÛg¼.~xû~öªKLÐZ¤UxŠ^:ûC¹–3ÒxJÊåÞ¾ÏT]ÌíÚ˜Àõh*5Ù¾»Ĉ*M?çݺÌ.Âì¤SûØjÐ(í@»KøiÖ}aÜ^Ó%Ó¾ «.Ežµ´½‚CØRê@í8ð„ N¨7]é [ƒ†øE^®dj5|íï›!êý77½Òùh޲çË" RoÖ=d4´–És‚½eÌŸqèëçoD Þ)ïç1êáËj”«‘Ûy·*à‚`&ž“N©¯ºà>æ¥M±»]J¯— þÜ~ÆÓNOì Æ\%ŽÕ¼¹óÉQ½e¥^Ýã˜ÞZæ—Žˆ2±C¶7wc¸8¶."ÇM—mêýY¼9Xqàusbýa¦f­âÛ\ÂéÚ¾ø#í½ÏØãxŠïI³ióoå¤YgÞéSOõ®6(U{®øzÝô —ˆ¤˜$êsZ/7àðé;›8ýUšà¡_/D”I;õîlÏ·Žm¶åµ¥¥Åš©Ã”IáðËζ–o òQþScpiSD ½CqŒèçeÿõJ1ÞëÚ›û“Üvb•'RéYÞŒŸ]½tw2ÝÝ«’½ƒ)Cb,¬ú¾Ø=;Kº½fv´n`oĮᨱßSÊýý3å÷o¾\¯tì%†ü Ÿ‘/RW²iCD7Ša p1åpÉP‹¸CÇõf©³£ ©ƒg× Mb ŽÂïß•‹­ A,БŸ…³_AóNlù$ŽGbmESû“Æ7æBU½ú¸æÌóÍôªEˆ< >^{©>R ¶ÕÅ€" –Ð4Ot^ù>9G(±ì«VÚf’ÐR)ŠJ¥Ñˆ‚ÔÙ>5@ÉÕúH˜7%»q­µ+ÚÄ·Þéôåa|@\Jë_A¸[ö§ø³ÞäÑ­J݃X:3ó÷†ï·Šš³xe ÉÑà@‚7CÓÛf6b¶Ëç_–n_‚®§Ziõ›Nq…lêú|w·hYN*0)—8¿Äˆab&wMYXr¥ ïûÎtÁÎÂ8ÕîDÞ’sÌYfDGöÒî2z&(Rçºzè2ÎJ×~ªœ~ñ5ª6ªÒ›â.FAËÆ*³¹CЕ”ºð-”"NrnÒº£wr‡vU^;“\¿‚L@äÀ¾X,h“qÁm>pãÒ;:ä+Ñýý“ñ¼gºb•Sq5©qýžMcã"myÜ ¯»š–µ­ºŽŽÃ¶:/OP$AKŠa¬É”&\aÝŒ\ù6q²k@õ.€KæUüÙBºèü@\ñäÍ ëãb*êhm%v¯Öòs“,æþѯòA¸×êM_f@´ ›ÊÈ!µ ‚’!fB’ß—Ì*ùG‚êè¯ÛQ=$³ÙCT|}ÜøäW€L£—?¾ï3ÅKøOê8²½ Í=ë mJÍ7?$UMXÅàˆ0¥",V½p÷5ïhúŒqŸÊ*ê.ÞÉw¸='b_>œñKmˆà¼ ?.oÉcëûZH?ð]Cågk:ÒpïÜd5¯Ån]1EMP ;?plÆêL’#Æ›xm¾²·'™ÆBØfXÚê'¤=&–ëºÖ§›¬ÁDj+¯tP;šW¤5Ñ ê™.JŒÚœQÛ¬„NQÙ3»æ]¥dº©À¾ÆFŒ—°p>•EÜ{oç´G±îbS^’‘^3<:Öߤhã;™0% ³\â‹t¸.›%L­E¨zâ?³“ÃÔ®…~Y›ÍÕ–@’ö\Œ,£nµ]²ÒNŒÇ¸ÛÍË£lÇ ¢Ù“ƒ­A{dƒÄ[ýõ§é³4†z¥þ®»aż˜O@óù7ÌѡɎÇM [¶Æë°¸Áפ—•Kñ•Û0 H_öíS“QÀë¹ ÊxùGâäYkqÑJw†³ˆ8›+n¸±8¼cȦ9S”Ÿ“¾›ùê½êºé&öûÕÄÀºc×¾¦bMg¢Á `æ2r°WÏ{XMêÎP¿z—y8›“´,Æè“Cþ¸Bͽ]BV®›š"c‡çzÖ[®3?«ê]üXö9:NÆzç|^ s9ãÈënýòžË ‘O³Ä÷=\•mýˆË6òL»)ð`õ•èüMSï‹Åæµ»[_„éˆSÏ}xƲxú|#¥€;CçÅ4·L»&ƒ~¾G‰¸Æœœ±†MkVâŽÄ,C©‡Ð gz{G8–ïU°‰Ì­Žb ·Çjª»a¿ÚâdMoûöœAKU¦“gš -[åín¼¾oá^´h6~Ìo#¡CDJ•¯/s¿¤Êñ®nõU¥¢=÷ò¤c2yQöDÓÙk|l%º”ËÙ{Bz½«ž®ÓÊfæw¦v×D¼“ŸaT±6tG/yÉÏ^ôê»à«T—zÙ•cºó}[›g¿È§÷( š³ç:ßÿ:È”5ýÌú £*`ê44ÓÚZÈ•‚8õ¦ÍXíÅgWj›Am>v¿£¤“:Þ™”»ÌEšÑb\d䦶+ËYœ gÍÉ…Dc3A† Ó¤Gªµï’Q &¥&r‡·W:,ê áY½›Z@¥EÊ——¼ReA­ƒ »K¡ƒ(Q]ÚõqR^VŠRˆDjׇ ?Ät5§sR`¤ZœÉ÷ã‡Cä HÚñPö‰µÛ«7:HAÓ7p¨oàüba‹É3W>"Lô–¤„½Ê\ —~Ê*5èš@y¨v|©2ÂK{ âl@ž[¶`\’itS}]Z®ÖL ƒÇWÖ$;0$jq çeßU¸­‘öw­ŽNåb`¬²+Äþ‰'Fƒ|Õ–z)Ræ™BËý@i«Ø•‘ˆ«’³#Y+‰ÏÃAÙ@ùûJ°'#‹ˆYhVðâÃ/×"~¾ÕÕK•Ûºf…µêÃ*cZ§uEÞïy‡¬’^züQXDõ£ì‡ÍͶҸmåsvIi %zÛ`?ã>[bÚ™ûEW£—aza »ü‡[UG¤ ñ¡^Qç•b#kZ…qš\–’Ò:Ŧ '~r¡­²T/çkÝ-§È…òÕ#J_ãRÌ™kg÷‰-¢ù:.ñœHÖ|¾Ûâr-’—ƒ¾ª^=Ÿcó@œÌQ<erÍ'ùÖå®§†ˆ2aT†íe¥‘Ý‘¶]¥¦9p-í5˜û{HUÇ~}hÿKÑàY£¹Ÿ³&1¾Æë#Ä­Ï󜶌Ú-vmh‚²4pZûÁOº\)& mk·û¥äéȯ¡ öá­÷—>(œ~yKæÅôŒ>üˆµëÑ"ù2•æÓÏÔ˜$áåühÿ‡ìÌ÷.­; Ü&‡£iíã¶ÅÞwêâ¨åŽ\!×gV:¾H-)›[?x{ýEÄÿyédñùö™róÚ%gs™ŽeûÃc¡&HNN%_ Uê¸ésïÌéÑÉÙ¨n¼"|¶!z–)š°’b‚98ë¹uå; ΓÈc6žùÔ[sUe"åjnÈ„0Ú=ºaÔYî¨Ä’'¸V{´Jt¯­+ 4 $Ÿ6“œí_ÜNSØ"®: ¦V5«R45µ†æBp¶±6T¡A- ý`æW:»/ã())DÁ8ùx:»AÍfÙÞ4ã M¦—ü#Þ”Ðá~H/kª‰ž¨áã¼X#O%±ô\Žæ>7Ÿ'ËŸ“ªŽùç¢ð: “ÁnÈ=2ÃmZ‹Å¯}`äµîl“H±[›~O›«´AY4Ò·€ß«+n¸bÆìÐ0i0pÏëùļtMž€Rþ¾ÿd˜’æÁ¡1z÷øímkd:õnD(óÄÒ¨xö±áí£³_5Fç)´²—<ž$§üÉ{9‘ÁAìþ–ˆxwc›>…¹Þ5uÄ=¬YOÅI°¢Mêºî…¼^ÿƒâ±¼iû $‘IÒl¹}ˆ ¸;ÙNEXÁÄLKv­Š¸½¶YiO «ëêg+sºšpëÐD× n´Ôh ?Phó…TKpªµë_+=e_W×û×mó¾ÌeO.~÷)© 2þÓâh¦#&¹6ê,pñ»/a—Î![Y~Nòæ²$uéc¼.¼ðw†Æñ1Û¦{&ì11²\'ŠO#˜Ž&×I· è ‰ëµ+ËŠ'Íú/Oµh£7TôÕü“pT#å’%põ`ÿy(U?™±v U{w×u~?ÿ²ucå§c]óƒWÊ?¦ *k ¾à‰‡kH@¬UhæNbÓ¼ ;UÞeÙJW±Š$¡Nꬪs„.uJ†õ/2ˆ«ÏT®¸ÞM•›\;dúÆn?ážX†jç ÉàbV:ƒ4žéMYJhɶ‰à¯ÍN‹ šjŠíØÏ½\€t(p»Ïr²©ÂJ¾È¤·ø_•‹1Ǽ»ƒñ£yuÁ!tìØ<êD3^€ªxù=ü•\DNWÈPß»“NY§ÛЪåyó4‹V>í»OJ¡•^°ðËÚÙø÷å%„h²ªxAºAêq€`õ(Ì0~[TóN’xV'¥Ö­C‚@•Íëuk5A’"ð^ié €âãåâ—}ù·òþßã{æ¦Á|]4¨kwÂ×÷¤i,g‹[åÈ%,ç§¥$eº!D‰Ç"òV«¥ÃtvA þ’V;‹Á»€;•;®)RFÝheCÐÍ‚ŸÅ"¤OÏ‹j´+ê>Ž–(ÕJáªpf„ؼUöí“3´N¾‡/ú¦uî`‚½qUý…%Œ¢¹¡v¶¾ÄòÚøs”‘#é £Ý*tù—«Ì‡©L§:‘M’G%ù)›æU;>ö{˜Üä«(•®ýÒ|6Ð|,EØV–b‹ëàb„)}?t´¸9•5ˆö<”8··ŽËÇùR¸åák <¹$qä½2ƃÖF>!ê§oIg< ß²|•P* õúŠß“{êSWx³‚}§¾Œ÷’´ œ·çÓ~Ò\šnÜuÅb«^¸ËD™ß0;ôìŠþë}csHÀcZÌ+’MÀg9³N¼¢î_5`šðºoÛ+üÞ]TRàôwºgƃÖé‹~ÔØÚw7ÏÙwF…·nu^†(&àÄV’ 'Þ/<ŒÏ›@DÏPyC{Ò©Ä¢"EÁ3ï‚HœÔ'Ì‘J7¡"ýHç4]ABÒÕ$¦]„CVÖ*ü«üjeñ^Yƒm¡ó½F9Z¿R<²‚ T÷$Ð?bNž¬·ìñ©æªµè–œW?¾Å]éŒÌVa_¥môÜšn¥fznÛç±ÁÈ[œÑ‹hI«÷i·ÊCôÔ/rK[Ó“õûv|ÜÃZBš|ìã(<È3ûi‘6¡vç®þë xž ó™„yIœŽÇ“¦lÁ)ï \„¬»#í!Œü6‹òµŸžŽSä_e2öõʵrSžõ3+œ09/ådYE½l_s³×ÚHš;ÜÄß<qÆø©®Ôú”Å5ŸÞlÉÒ_<ÞzYÂã+9šÜ.Ô©u]å#1vgO9eÊiÇÅqbtVÕÀP†Íâ;I^@´Â÷ZXŒ¹Î|¼my£øÄ¦}Z,0|câbšì§§Í;îä 1AúB꽇ü:dã4Á'jlîCTÞ¡yÔ„|@I‹œ¬MúÅÇuõ9.Þ&Ð.ó=0³%‡Ü®1ÿcM‡ÇIcYºÑ–<-¢}TìN·ëo¿JPÅÐ}®1†Z8’äOwNˆFÜï-àÛ··W¥[:cfНeeÏ;—x»ÉXÛ}½ŠQ‹›ê˯Ã3Ï@Æ\œá˜+¶!ÛÊC›5nôþTÈû!Ž÷,Hü¤œÝ;áŒçdêé›HýRÂðöGõæ:[β$òx!ˆT­ hÊqà«‹7«eaù ÄJ‰O>×8êhäô[%úÚÓ[Ysü¨7è±gJж~Gph½{{âX#ó@¢°îÑÚ¹ |öÑfÜZ×xÅþÒD®Ä°øì+-×ÞAÄå}NªEb[Ö7í-„&Ãw¿†{PŒ=#“a.Lîy7›åøùÌÿ¹::\®©;~ù¤{*õį{ÜÃã=¨žÄë|Ú“—á9(¶âímOÓH»¾(ðXcÆŸYÅÖtÊ:gdí¸¡¼9I$¨Ì2ÌB#B9’ÜùzÓH¤°ö5¢5±¥A ýM ÐD‰SE.@òÝl0-»èÎçä™·IKEÜFªva-ÑüKÏw.•eC… 1Ü•Nù/ïÅM£¾jú» °×Å•ŒDÓ¶3âÙŠ¸ÌÝQOMXF?s5ÍÂÀçÜtv'Vœ2÷|{-ˆ/ˆ‡¼‘m A´@ …rôÁ eé*'¾) Ú×êH…úƵubëgWw óž‘LƒV¥X6RjT.qNhƒˆ?NŒˆ÷²?\7yð¹¯è”iw*?%ê¦B‚ÀÌ”´¾¤#…¤®“ÕtDã5y"}Nu÷YäÑÜ{CD¨ò„Â/ÏÁ'q=M2a7]Ì”2NØÇRñ¸c§÷1ïçú…«xìŸÕs<$‘tr8çòøàX(}Ô†z0ïô]d§_áÖ‰59»èÐ}9Õ'òÖ·_òÞÐK7i¡~2áÒlç“X^e"ÛÕvpýöÁdd®SwkääuœØÎ{–»á'sr”xË4ûÅ{…½ÍæË*]L‡N³Þýã ÆoQî¨ÇJóm[0™ sÕ¬-Àó«Ò¶àfó·«ÙR·.ÄDÍ2·J¶ˆûæ¹ð—)q.’Å꘺û¯rFçi"5Ñ\v=1òE±ÛUå‡ÓûÁL—OMµs|8&wLÚ|sN{Ý£‡vgï2ܳxDül§•¯+gÍouÆ€Ò–™®"Çù1¾žá$Ž!%ÑéÎB`ŸÊužú‘àä—ƒàÈ9wƒï²Ï6Sè‚Jq€þ‰æ÷_±lî†ÇÓu H:Ç´[=´‘Ø Ëq{k]¸w³ÞëJŠ-Ú‰kKéu¢¯Öw WŒÏTºÜÑ~õl°Õ·é niú­Ñ±Fÿ®rÑ}ët{’Û“4²Ÿ,¿ÄÎf©þˆý5”¤+‹7:ÞÎîÆó‚™C3 Í4ÂmÚɵ®øåøøBwG8Ò÷ÖË äf‡j·“Sh4É]'Åm'|Æø‰[ªG0.˜?õó•Uã /£õ%jTG‰™v„|ùrŽ$J¶õiî½7@_LÁ\Ïq-QsëÐÙióöS§!íÂ_‹MªÒOÖˆºXǃ7>µzû¯ñŽ=ãqýNˆ’y¥ÔÁRì/‰“-$@5Ö‰—9¡[,qÚÆÝ1Óºó͈Y‚¶¥PdÊã\ÑIÀÒ‹æö3ÂÖQǵ™µ‚÷§â®}9zµ¯ÈoÎtxDê@òêf:4ë)ÉÅ[TîÆƒÉvKö³n'ðv2—>8G4%“xåÄþ§zÙÑER¬6@Á€ÕF|íѺf«‘CBíòr‡…]:µE@ïâøZ’õ4ÝãöôõÉ}Ûã›TÔzxJ%û Ì$“ƒú{xIòËtb“'­9Ú¾èŒwÙ"eÛc6˜@ÈdIZ,d’åGŒ{þ-ù"ZÂÁÚ#ÊÓb!„MËœ©Œï[½¾ÍÊÔ×ûUËZÙûúHÅ‚÷4LCo€+í”ÆÍ I蘭“„ÐÔ‰ ¾'Xób‡/ƒæö¸n5( ±±ðüêïH¹2óŽy)ÉQÍìN¨_шK~¼ ÔÒôŒ!}°pZÛåÍÖ•‹SŠdÞ…‰ 9½:¥/ñfOIÔ¨B²¹ËýHú¼ñuµ{¶›Rµ×*òÆ'զʶ-ûî„ðn³•Ý š^FaPçÀšæ–Ê“•¯\%A»àé•V\uâUÓ°Eî·•ò,ç\ŒËï éÁü®Ö“‘–"Z<"© màsÕ­÷M“¼‰uü:™3þ½ßem å¢ úÃyÅ ³õІFpv¡ãúHÙmHŒ”@‘+Cˆ…~Ñ”\î…páYHÚj-–ÐW%úf̪Kì¹\~ã «¢ÓžˆúqÕ £žG–æÀô¼*ä軑ceä•àÛGb?'M£(ÞPȪ™¾¶Í•VÓ‘>|XA³ÓYSPI›zÂ<]ðxüãvƒqò!Ú[5!01{O„—rKÿÃà.M$½üòø(*ì8ejZþÝ)G¥ãw!Òvµ‰ôîJ£l;TƒíW^†ûâNúÊJ soß›`å2¨®£®¦…Úk5äòñ*ß7›W쥽šä}+µÈ,³ðÃ%y]s–‚7ÂÕªßxï™Ñš´”G“Ûõ¿L7ÔéN3·Í)pº[«u[Ä“ïtGA‰ÀÒF¹G¨.¶˜RŽ×µjÞýùÉ×]ï›;.©/ÒLõµŽlñSL›Ý%ã-ë~ìèêóÆèëd†Õæ<Ñüš}²[  |\§ KuàL×R` ¨ôLV~cÈC•ÞÒèN-I+55F8’{mÍòÜ;ßóÌ+¯=}&—È%ÛˆêÅâIõfjSïš´œKä°Þmû‰-»'`>œ-Äòëós¦ÚæCýˆãä´PÆþ¹ØaχÎ]ª¹žž×WÑÞ„YîßX²ä¬KQh›ÑptL¾€œ€#çׇ·?ä ôÍ.ÿkgÊ endstream endobj 80 0 obj << /Length1 1467 /Length2 7558 /Length3 0 /Length 8560 /Filter /FlateDecode >> stream xÚwT”íÖ6 ­4Ò1”Ò0tIIH·48  1ÌPÒ * ÒÒ¥4Ò  --Ò݈ô7ú¾ç¼ß9ÿ¿Öÿ¯YkæÙ{_{ß{ßûºžµ†I[GÎnQ‚Ã<@^~ ÀS  €Ÿ_—Ÿ_ŸMŠt„üËÏö⊀Âaÿ ñÔB¢| $ ¨‡TÝ@APD(*ÁÏàçÿî*P¹C­¼U8 ‚Àg{ wör…ÚÚ!QçüëÀæÅÅE¹ÿ¤äœ ®P0Ð!í N¨Á G€ … ½þ£»”é,ÁÇçááÁ rBðÂ]m¥9¸P¤@‚€¸ºC¬¿Gh‚œ Æ‹Ïзƒ"þ èÁm Wåp„‚!0*Å f q N詨´œ!°¿Àê¸_È üw¹¿³‚Âþ$ƒÀ`¸“3æ…Ùl Ž€–’:/ÒÉ Á¬AŽ8*ä‚:‚¬P€?­ƒJr:j¿çC€]¡ÎH/êø{F¾ßeP׬³~ wr‚Àüßý)@]!`Ô½{ñý½\Üæý/Ë ³¶ù=†µ›3Ÿ êâQQøƒráÿã³… Âüb¢‚b"ˆ â ¶ãû}€¾—3äOøÛšÁ×Ûî °Añ…Ú@P?øÞ;€tuƒøzÿïÀZø@ À F¬ ¶Pþ?ÕQnˆÍ_6jÿ®PO€)?Š~@ÿïÏ¿ŸÌQ ³†Ã½þÿY1Ÿ¾¶¶‘¶<×ß#ÿ;(/÷xó<Âü ¿€@õàûŸu´Aпûàÿ'WfGeüÕ/ê¢þÕ³ûß$`ÿ[!€ÿ,¦ GQ`ÿ‡éfüÂü`Ôðÿ›ïRþo4ÿ]åÿÉôÿîHÉÍÑñOœý/Àÿ9A½þF ¨ë†DÉ@Žì¿¡†¿´«±†º9ýwT BÉAf‹¢4Pˆ—_è/?¡õ„XkC‘`»¿hó—ßà·à¡0ˆ6ýýŠAeñóÿW ¥2°ê5‚@qó¯’òÏ"Û”¨þ³Ený[}Â"«+È µ|”% ð¢dj ñüÃn/ ŽD¥P3ûlà®ø¿-,àCIØ ôÛýÇðAœQ:„Àÿ8ùQ^è¿Ma1Ÿ3j§pë@òù ‚Ý\]QüaªûÙÞˆ'Œ?3K†Ø×„´üª’£õàY–Â:Hùe$À3œo‹ìQ³ü§—‘>«Vª4Ó T²°o×”wù•¹øíÄ{µ–±ÎKè'£Ò¦-£ÕÛ©»ŸèñÞçtÌSDÑr “ä$Š\{дé_wàÉXÛöè±ù<®éšŽ÷xD^¬$ªÚ¢ÙÖQUœ®NA'þ|wYÙhÕ¯¿&|Jõ8kÙ)&xåYd²æ;f5©¶ ü8J⥾Áþy’núO¯U݃ÖYÃ$Š’ýt B8•Ïçs ¯³ŠÜwÞ‘z[)“=¥ÐÓÈaÒ¥Âïš›Ðx@evÍ‚cdŸi¿CEÔšûn£À|!(Ü,–œ5ÁnûÊÛZjAI7 ­ñ[øàåù ÖÒàªãýŽ‘föt»²âc¿Ïrz¯íS*À&<¼†Ù)²œnRN0ÿýóFe`²”gfOþqJ[¨„tl&^’µãCUíæ*~KkíÎ4hÿå„Ym­.à-ˆÔÑ¡/ßÖ`MÖå•Äð{Ñf„xNBbåò~ŒŸEƒL|Œ^fú}ÜQuįõícQw$ñy¯ï«†õ«c#6K«ï‡Ö¼A&ûµt E›îüJk"Õ?“‹²©\$kÌÌ£¤Ê:žS{mú„5\HO½©ðÑöÕ¤mêäZHÈ#Q‘‡¤oë/ØßáùƉÑösç^'Ê#r?0϶ŒÊÀfÄ«”židºx8bÔà½ÎdaëSî~ºôjñŒ#©ìŽ·Tpfl”(SˇFgx a¼ëËJå³zö"Ê bÎlûœ(¶ð ÁW¬GΉ vFpgü£*1Zõv“ Õù:¾“oª$KvZë/N'Iå™ßžùˆT¬)^{gòTdµîÕ@9T [åDæ"ýdÖüƒnç¨ÄÆRéÔÉ8§—Ö|>Òºñd ¼&hãf‡ÞäAiÁ<¯ØFü'Å|}™Ìýd%ŸäÓØ"´ä¾M?£É³L{æ¿g@èW»x¾/ÔrÁÇÁ­«Þ{ß´‹OEZˆoÿ.ÅF´V“ WEpÒB(Øõ>!ºUELo„ûõÜz¶ ¢$…RQCã²¹GU -&uÛ=róP{cV61¸G…”¾ yäÝ`aFìç}RF®ÚŽ—–Qlƒü|vƒktWóöºŸÉ™_'B|€õºZ"ìÏq&uS¦Ÿ oç)ÐWÞÍÚçq¼Æœ$¿ê¯°/ä¦É []ëÜê½å±ËúæÕ8¥Ü · nâ£sZEcZÛ"•©²>]¬õ,ÚÚfˆã^LŽ D†~H°rÒæ¾'–ÎVÉâ•J°8*Sõr’A¶•¤SÊèiÜö|ð1€N')ßUÓ°M”´L@½®²‰Í:’Ïþº³9#Œ´¸Šã–æ¶x6"µÊ ³Gߤä$nes…6ëªí:±åÑ,ܺAÚ}ò½ìû'ÔÓš]{,‡’߯É#p¦ç­gbRÕ-wfŠc«9áy(¯PïêOà6¿£?TÜWƦ¤)çšWÎ<Æã_Ú?9Á_ðÀp3Š–Vú”T§ BözI±„Êž®ÒÁ|´˜#ï;}}¾9˜V£ð`VîÆ>órp —à(ï,­p^¼eº=p¶Àá¨Ùø´œë.v­´+"ª›Ýfa~¾ÆGœPmgÍÉ&"7×hÙgã(7Q£L[zUõ4¾{Çþþ0 žïå{MšÓö\ ×Õ$û <‚H–7u­ ªfLÀ¿?Ï$“ÆM˜±ýJeëÀ瀫Ù&üLÛt•ÈÐ9IW†°¦;êqÇ%bõñ “®§êÈh sÈ´Œg€­Áü‰ÝHQëW5¦ªÂvëâ×)zß ‡k¯]îäÂj†ÃãÉ(öp?C‹Æì®~j ;£…IH.D¶˜j<s£Df^iÜêDùÓ]‹Ê3^Nn¿im­?¼Õööª¡åUþXO¡lII®ÿöK©á‰§'‹OÀ8i}Û´4Ä ˆŸ÷1m'FüÑ ¿*íÄN£—Þw:—¡›Þ¹«i*+‘#°¡HEã¿Èì#º‚EжoÞcwlä*¨óV]Zþ®˜MþJAÄ6cÞÈ¡ùÝ–]g“>T+Â~zr>6»;C"Y³\JJ™âf9\V¿Èñ6mŸ|ýÜÏœ´¥áâYnȦÖáê´’Ðö{¶ÆãBì_ß1±`²š‰…ïÏÍŠõºìúÚÀ ¹µgï·?­ˆÚÝõZ†í®7¸“Ÿ­ÖêÇÛ¥Ù²ïêws‡›èÙB4¡Üc¡Ä@‘㉓Šh›'sÒ镳^ÍÒ£ô]ï =|‘ÉjÖCU35Ø[}Z¯ºKꋣ;„"’µÁ†*äßZ†ãÑíä‡?ÛõuUR<ûåÝ/ùñ3eŽ’Æ«·ÇÕA•‰Œç%™øæÐÍ/võñjâDLÎcüc#vި턇°æ1DáR߀$Œ^]qXóT'84Ê#¹àAGU­ÿ•Hn“UªÎö5$Êÿ„&a4²ùžÙÊ\-Ó©òóØÒläÁ¨ÂåÌZµgìëôæ¾³Y}pKèj·2ŹÓfç/n çóÆ–¿å\‹Ï;2ëÛÃò¦Ï›u¾ÜÉgTüI(îËwpBÐÿÚ5PšP…éÖ½Ý-¯¬;ÈHÑ>ú­€ªŽR·Ì5àÖ~ôà¬ç«ñ7ï]“Ùh´Í—ØÑŒç±Ó ÏËgÞÛ;ÓúþŠÊ¥•¥3`!7îê+‘áÔ<„ú~(õdƒ|¹%Ÿ (±<º Rd)|!fÿ¨sñˆÁ$÷u°Œ®ñqÚHÆçM–ªè£Ÿ[ÜG|ÒùÊßÌÏI„«#š$_Œ-y›‘ž‰oJÄ•nu²~â!–<‰ŽcuÝ<¸¬^þ’’R:|`°Ûw4 ]ª¸bwíÚÏÒ¸ŽšYÏÿXĺrúæ©î÷›™Ò2.Â\åQê *×îyà³FÞÛô¾ñNÁ ÚV›á¹´;‹ò´9o•öØügÉ&ñU¾Ý|õ9dð‹½W·¦±mNؼ^ œª*$;5ÍòïÏJØò÷; mvh¸jÈ!ÜÞ¾z`QQJoSQ3K5§ûŒn^6Â4 ÁܼÎó9gpXñ‚NÌ=æ°WÁ GÊ"Á :CK·“†ãD&Oðk!ÞiàôÅâÜ¢—×纚õy¤v/ȃÐ}hãîŸc¨‡ç—žª{hÑRyt| Mûål8–ò¢–,,*DÌ•˜ÀÁçfé©£ôõÐëÚ·X3IoífcUù 4‡µÒ«{¾ÜCg³D í¾MÀUÊõ[<·ŸŽ]³8$Ö¤<^¼g°¹ôX±›JÈÀbÒïW]©x.§cSØ]G©rÂð±¶åôÌíBZÇ-«Þ/¥õlÇG {\&>}90Uæ¿.Áèr«4;j¼ÅÉÊøæfÞöξ!´¦V¥B›¸knX é£<Ë* d¡cú\ŸÌÅ¿àèo'Z±Fxy l±ÏT€¾ðÔ`¬¯Ì«“9ŽvéÆçaµ&ªžöcÑþ«0gàÇàL={ÞK9†¡Ä“aÅœÓÏÍãU…ãÍêàÕâÆ@Cçï¾¥ÄírM߯/3ßÕRëJ§àí!; ­àŽqJÎê6^%òù!}¸r[kboåL™“líÚí¨gl»g“óWFÎç¸ÛÒ¶¿œËÜ9ÀÖ”oä’g™¦›ùDŸŠxbqó>ã$8 *T^JO)#Öy¼O¸ðJ•ZdPiH!´µª )ô´¡» ‘>DòÑü‘Œ0ÐG‹Ìq2à™b¿7êx';AA–šùI£Ö˜¶7o¬/?„þÞd¯JóúÙqf”^%ÃN‚©?»ØŠÃ£”&îsì ¨Uzp`0Ô *û" žâ²5ÏZÃö¾ý”8*â–8–€Îv[ °(?ÜR (Ú@/ÞýR=Oq²åƒ{A BßwóCt–‹ìÑ£iÙ uv’g:ž´§Õjû–[K :FöðójK¤;¥°Â=wf y¾…ï°°U•©m–SW¾Ç+Â>v?Ð×í—÷öþ„V¤íü÷›†l¨CÁ¥AÛ‘Ô¡{îσ{^—ûÈ7Ñ™»/§Jpxñ0p¥Ì±M(‹@9²÷æXBsјAÎpñ²ð%õxÃ0\† “h•c¾ÊÞ3ƒwÍ^„Ί¤]öRúF¼×AÐJ͘)+ž¾ 7Ú2è1Æ8n^ÅRÅH|Z Ò¬.+ß©úv𤣻¸Þôš›AˆÌ©Á¥jõ¶uGtdÉvRÉ–UoÕÆÑ-Yk¤´î7•p² íÝt@Dó+°/:9šÇ¹ÄɽõŽåã²¶ÉVI!mƒ‘¢x-+¤<Úfç·ß»FjßO*Hþ?~ «v+ÝpD»á9g aa²i=Á&ŽZBûù­x¯åÞÜA©¾éׯ¸á²dcAŽ$o¨ÙÍí1\ Hºviî`ŠT²¡2¢6qãf1½G‰$hwl\¤Ù•KäïâÐÂg# н ÝBïŒt_`ómÞËì«åJšœœ]*jèßžã6ª×X}PÞØÆ@S9êËÉeQ˜àÿYòç>QvG#|äÝL*¥;ch1L»ÚŠyŽyZèÁ€îK1mxÓÙIVL²¯ºajjýjH-ë–TíüÍŸc7e}ÙÞ‹y|­`š&ýЧÑÖ™WPÊmX×¶j˜€eõAi¥™ÄΑUNâƒÞвªmQ]üzÖÈŒKþq6Ì£—ÙWVŠ'`† êϽ]ºVéV'—t(ØgÍ!7¯œ×‘ÞoõÝ_7l×à™kWÝzç]i.÷%?Ì#+wT*à}ò²"øÉLÕõ8Äüa¡°`\’ÅÝz30“téÎp7ÑtSe,%B®`K 5»öϳ(£~Ý“¨bÿÍ·Ñ@À6‘ãµí]š¨ÄððR¹ëc¿‚ìjÃ;Â<©JlîyCNš%øz‡ä7Ū˜aaBú×jt¿¤/ò6…ïŒÏDcL0Ãá»9 ƒ íÞQŠÝ® ó*2QÖsæ„Þ]¦šÄ»¯6¿ÎiòZ&‚xWâRÑd¶2jö’]Û ’+R±1ŒµÅšMO7¯Ϊh„äG.;mÜc£lOØ aöR¸µ´™¸åòÚ¢¯Ëw£Ò}»¹€qö¤ÍÈ÷ý¹z¤õ«¥)ïïéÞÆ¯:ï×GYØÌMw¸Ìë™nÁ/]|ù<§DF’X{ó¨ˆqYÚÔ™ô¯¼lÊÕ‰Ì^ ÆÐB©·²©~M.: ê„ÆT &[1õ›^OÝíeeï&uÒïS}6@‹õƶªpöäaçì}Æôü|>к©!@ÒZ([§pÖ„-`°$áÉ Ø‘¸xaNT3ócÿÂrÉÿ͵”úëXÈnZùE a6fX’lô鶃ŸéÌ •àaok*ÙG8‚§͘¯ùºm—ïø£¥eÞÊç>osY›j4%ÆIw?hEVn\‡º·^ü¸Õ\¤ö¦;™ã}ãˆjkÌM\MêõiOš=~¤¹LVțȜØâþIÒÏd¾è‘6^z™“]ptªÿÑg×l‹Ü!õå9OŠ ×…ÖáI›Š™ÜéSù” T{âÖ/=V\„fïáÚæ,MhyÅm8ûGo‚íÜ}űة•(´Þ3·Ž¾»Ä.u¾È-¾Lrºw=^¶%&Yÿ½ÀÅdYÀú.”¤‚ëStr)ÙE³¿•¡¬Ö9¼‡§Qñ\<Â5&[ÅæÎÂ=¢ÿÕT=P²oð3³X¬¾Í;ôTg˪UFÚ—î±'£(VíF^7Y,ßùž YØ_ÈÖ¤sASà¯×mËJªŠ"nôãÁmòˆ‚æ"oÚ'äRR ÷Ê®2=O¡hï¼5”Jaz­ÿ<„#8”qàqŸ<f5ó®S ,Í2ù––4ÝÕOÀ§«ŒÕO—:ü%Ü—>èI¨ã17†É5N®³!—Æ)Ž 5«÷þlæ ù@†t<’õ¢2h#íCY²W©Ú/g°FÖðùæCn~X|u´â)"1ë²Bùª¶´™ˆ¸ðû%// —4d›·ËøÁUëºèÅEÁ1Që­êœM)̰ ¤1rèê¬òöhI *·Äù—4ûÐèü  ¬$q’%ÖHOʘòíeò~¶Ñ&EÃ)µsE3ê» _Ç$«}y  8Ö¢’Oy¨ß€¥Áñ«ÉOV×x=°’tpk˜Â‹ôA÷”"Áê[ì/ÕÉÑéºlJz>˜Œ?ºa—_ÔÙŸ,Dwl–,ìG$ðÅê¬2qšô—Í)aá d$j5µaj«j1qc¿¢ú[ë¿ê­ªs¥î{WmZ®‹ÎÚÚãI8.lP°øùÊùS6[bm¤¤7÷bÞ R…„V-ÔíJë5fËžYä¢>û•E™ý /)ž=%ðXåÌ.°ê:{M¬búK#cî ˆ¼¨Œªi åð-߃^mdIV’^š±j+Dù1ÖÍMªz¸Z1©÷P'oÎÛ@Ì3ÒYœÕYvEVÞ¯”fAǯ ¬p{MDa±”>l0dü£E[U{ÛϘñûFßHï4'6"ȯ&¿<ÇÞ-—ÐÇïxPØ¢eRáäÔé:AáÛè`¬æ”t½b1}y”ù“áÃ@"aWÂT›P 奅TÌŽ¯_2¢_Ôòz–}[*ãÞ@IXÆ#Ù¸ZZHRÓNÿº’ØîçBuãÍ¢kä9<=;<¸_I‚ƒJ¸à ŽCL„†k9Ó&¤YV¹èÒjÙæ;œž?,µÚrÞ‰êÐôâøc:šwŒÈÒsÔšåjmÓರÿ¨eu}Š>^­¨÷™ ݱBÊõ§¹ u/±ýÙC«TýXÐR.¡ ÆŠ¥å-7þ¸@ËŽç ÍWÆú!—¬9Tš_òS ‹U¦ÑMÖ/¢Š¼Z´(²—ç÷xrHH®áE® jU§‘2dsd×’âvó•<;5ûDSñ"8„Ò'ŠS£{‡0Sô¶5›ƒ G"}{?¾âü@#Ú …<Ý«.ÙWV=§{?¼Á\áÀãQ‹ƒ7¤lI/–ÂoÛvnUˆ&:üºdD VÚ8ünN0¦7'‡'ž1Ä4(¿e™½—°ò%GcD’”›™ªÄ…6žʩA&Åâ`öÛ³Ól!™Õ§Ô_S&¡:0óù…s×ò ;–xL‘³ì§äµª9ÆS\™ãíµÃÀØê¥nê9éÔÜ¥([•cº²V“°å‡–GõÒúÛ­y³-ª‰¼HÄWõÍ ³ÐÙùíd«éÁÏJß~žòˆ[á"2ƒ”rÊfpÌ:ìæ•&£,Ë"%Õ÷KÛpÆòTVåsÇ#xèH¶œlC¸Ó󀈞Ý:\sÞÆOØ÷pkHÂ{c_>YRüFúÕY$ðöÅ"¿OµòW—qnA€ˆ–4šDkp¯¸oUT|Ëó<›×odtèCRŒ7 Ïï”;³¹{®¤)Š~ãf˜Z÷jX[“èVèF–9*Ê}¸â׉ê9òÁÐ\?þÀ^üQ×cÉÝ„¡z£´}ï"pÿ#³À4zeÂQgû‡2³pFF¡ÈˆnÍû¾/¿Ðû”°†a_Ó#ý^)í9TsË™cõÜÚÇá{Óc 6%Gã¤Ü™¹J7ØúQSP’ŸKýû}„îû¯¯NR±p@NÓIm¿FW8i˜Æ  $4µªd[¿P×ÇÍ:ì©ã–QlÝ»¸ùøÓ4ÜpQøÕ‹œ43þ”10¶÷¶}fµûpnÌÒÜMÝöÂavº¥1r æÙh×ý2¤¾¢ªV:(óVæ±ÏØ X,nùÈ~i. ­¶ù—O~xÍ{Ía=iÔ©a.X¨“G-† pz ³xzÃ0Tmü3ƒá1-Ct½”“Û}Uc 4i·k;8¨Arœµ*Os—5¼%Êoìù-nŒî,0ò»½ ‘ôùl¥™K,UKÏzÀ¨e­ü}RU) w,ÉœöHü~Þr_ë¦E]g KV‰8ÿ‰º©mÇl]æ")ÑõȨO´CÛJâËdû¤¥Œ_ù+5ÝìíÇÃT»1¬×ÄÐI&rMî’\ Bq×=ðTÙ]e\ -¨3}JJÄèªqŠ ÷ßje+hë‰Úrö×°\³éë^ ³ Æ'¢~Ræ–‹qåV!3sÄTæ.™`¢äc‹a8Ú["âp˜•94Ñ}d¼ï® ±U®dÍHQ÷qW(YF¤: £=!â5fpTÚ陥©KK’ô–Z¯ßŒHxþltÔ*ðyý^Y öYx6Èv¦ê‰éÚ¸ÉðcŽ'ä¾×{¬sÕ ‰ÃãWgøWLžsöÎB¤‡É&þæQ)-TÑ Ä÷m8r}bÿö_® endstream endobj 82 0 obj << /Length1 1867 /Length2 14734 /Length3 0 /Length 15895 /Filter /FlateDecode >> stream xÚ·p¥kÓ¨ÛÆ$Y±mÛ¶Mlc‰m;™xbsbgbcbO¬“ïÝûýþ¿êœZUYÏÕº»ûî~j…œXI•^ØÌÞ(aoçBÏÌÀÄ•Waf01±201±À‘“«Y¹ØÿÑkœ­ìíxþe ê4vù‰»|ØÉÛÛd\m̬ffN&& ÷ÿÚ;ñČݬÌò {; 3¹¨½ƒ§“•…¥ËÇ1ÿó 2¥0sssÒýé¶:Y™Ûä],¶'šÛTíM­€.žÿ‚ŠÏÒÅŇ‘ÑÝÝÁØÖ™ÁÞÉB€šànåb P:Ü€f€? (ÛÿªŒŽ fiåü—\ÕÞÜÅÝØ øØX™íœ?<\íÌ€N€ÃªÒrE Ý_ÆrÐþî €™ù?áþöþ#•ÝŸÎÆ¦¦ö¶ÆvžVvs+ @QBŽÁÅÃ…`lgö‡¡±³ý‡¿±›±•±É‡ÁŸ™$„•Æþ]ž³©“•ƒ‹3ƒ³•Í%2þæ£Ëâvf¢ö¶¶@;g¸?ò³rš~´Ý“ñ¯›ýlgïnçý7˜[Ù™™ÿQ„™«£º•£+PZìo“Ü?2   €‰‰‰“›t=L-ÿ¯æéüSÉü‡ø£_o{€ùG@_+sàÇœ·³±àâä ôõþ·â¿ Ž™`feê0ZXÙÁýýC 4ÿ‹?.ßÉÊ Ëô1{̦?>ÿyÒÿ/3{;ÏÌÿ¼_F)u1aÚ¿*þNDÄÞàMÏÆ gag0ÿ1dœ¾ÿFÉØêï4þå+mgnàþ+Û6ýOÆnÕßËA øïX öS Pý3äzLìL¦˜ÿŸGýO—ÿ¿ ÿ#ÊÿmÈÿwB®66ª©þÔÿÔÆ¶V6ž| ­«ËÇÈÛ¬Ýÿ6Õþµ´ò@3+WÛÿ­•v1þXa; ›ÿ´ÑÊYÂÊh¦dåbjù×´ü%WÿcËl¬ì€JöÎV¼VôWó¿t«eúùãÕáü1’ª€›óßGŠÛ™Ú›ý±b,ìc''cO¸Kþ v€7óÇ.š=þb#ƒ½Ë‡ à£<_€¹½Ü7ÊÁ`þCôqEþ!n£øˆ“ À(ñ±¥ÿ¡?¹ˆÀ(ÿ}DQüq}ø©þClFµˆ À¨õâþˆbü}èLþ¡˜¦ÿ!¶(ïÛ¬ÿè$£Ù¿Àü²ÍÿÁ?Èê_Ú-þ…Ñ-ÿ… û·ñG^6ÿÂÄlÿÁ=d´û~¤aÿ/ü8ØáŸ*>zèð±öÿÊ›ùãl§áÇÙÎÿ—áGÃ\ÿ…™¹ý ?2sÿWÍ©xþ‰ÿ5N¦®NNoÔ?þcÖþ‡ÿ|}@S¸å{SÞ`ëúàŽ‡Za|wúýIþ9ò}Í4jzïe§N×'$èdꚬ/›NwÂÉ#}(k»âT·B+D¯Þ'­ Ðam‰ÊíÏ>/†ñ*3ûípKÓX?¦ŠN„¿À~¢Wúåóêè£ø¼´[†<ÏÑ• I©ýÁ}@Òãû`Åêxè¾ò¯Yø—ŠYúhõ(½ÀÒyò|“ìŸ8$P.ô04h—Èó·wsh¹SïD2ñ´p¾§Ñ¬ÅÞ:[,1?½Ö+ÕXœ{pÉpupÀoÑÆg(¼ESd°½ËŠ×~,y´òå"Ò¥®Ñ£0²dÖX©DÚ5÷×¹/w1ïå%‚)ñ ï%Ö•7c:‘(bÖ´F¢»Ô±~v™‹¬wÜiôš[§~Zážýþ˜GÔ¶< héõ~np\ýAšÚö0Ò<ºÛë«Y*8(øÉ™FÜR7bm•'“ ²Âe¬G(B·â–ÌõiÂçýåJä y§ˆ‰I‡ ²tüÓ9{žÏUŒoUã¥B×Ö<ê¢;š~Ð{‡Â»Iwêåe®%«¸QV(U~¦xï×üXJeÞz`ã|PãåVƒX¹'‘\ÂûÒÕY1›´dÿþbõH„ÞOëGîB†s*õö8öBeâ½ÓHú‰ÃÆÀa‘ î;³Ã»oßD 0ì5/«ÜÃEFb¶Õ8ƒó¿v©äö8+¦K G‚•Üïþì‡5!=Sq#¶mŽEÖTãÚè)yq§«#§,^–”=â óYÖ_+îÇ­ ÂúzÛÀRß©ø@‚…²CžõkœÔ°s¤Yãê O_Uí¡€Ôk ¤qvb—xlf—ÌÛ¦J¯”m ÀË•nOA¼¸q³ÉOñfѲ¡î.ܰò©.sþpótxB„º“• C`òT PTN™µ!WL‹ñ¾˜c½ã•-ôDÛÂ_í¬W¿qËò_¯G”lSL0\ývú× Grd¾²ÝÐ7üŒÜ=«ò…¤âÅ89ì:Ýœ Ôß»ÅþÔÄQæ!Z_`LQ#a@vù~Rb ×Ǧ\© +±ŠçÓóÔ¡R¢n½M #É ×0@.Ô‹ÊL‚ȸT€Pô{sBÅqÔÁ‘jL÷O÷œü\ú‰ŸxÉX>Š$±háN"Ážë~¥NæSóh¯Ì7y0™ ?cä×Ä—MÈÌTî“þÎ×~d{ÑÐü¸”µ1by¹‘¼YuÓØX[›)8‚k$xÙr‚o8ž©›ÜuÃå¡ÄÇÆü“à†ßeêA d‘—#½µÅ×IÖ•ùˆõ9C]Ò*«AÊ¥ª~fÎ÷·páÍÏ”\oÓñ"@¯­í›"›±n¦á½t[AíÅ÷šÌ¿L#ñ˜6 ¾]ËË<Êçj3UŽÇºyslâ$-è=ôÀœrG2HXqùïÁ“²ÕfµeÖdqŽG¨{é°%Ge½ÃEuD$s:á PÕ=3‚é¾½±Í¢o_Ñ¿ ¨6|”¶Cv=̱=—€ÂæidF‚YJ1ƒ)öä¸ÿÒ³² @, Æ‘³cW½v§(§?™«­É‘ôz(ã>Æá¦LØ£í~±TxjXðÞSD ¥1ƒË¹™þ´Å„´j,é¡&‘?=¶jÖüZ…STe»fBδœIód”q=Ÿ¸™Èh~ÛŸmÓI®$Î’ÏC¨!L­*"Çø‹¯ëœ½B4G¸pó>Û†·Ú{¬žŠ´mI ÒN*&$ $˜Ë[eÉ>µw@ ›jÏPóÌDøÍ_ÖÇ^Þ}a.UuóíS|'¢çžüá;GÀ·¼:ƒÎ{c—"!Eæ“|Æl‰+¢¤&VOBÒô]SdyùÅiÉA×u]pÛÊ÷6¯©( (X4›ŠÇo$}2Õ@ˆ% ‘XM‘O¾ÔqkªÃ«V¸tù¥*hX-XÅíÑCàJÙ ‡r3%8†º“Zá¨ØC7¿•ójÕ”ÞoÝ‚òဣt o+xANþ–‰O-‰®XWqÁQF´6Þx0÷@åû…8C!slV<©M%c·/\õ LÃÚÜ Œ:ߘ i*ö†¢Ñjbåi‡LBy½×+Æa«”Y±54x—ò;&ÂçѪs¶¬è:¸¸¾-ö‡†Xäòëño ‘Hl=ÉJ<¨å›<§ÅwiÆØPÙXT÷f¯˜ÌVE¯·VüLù9¦·ýúȟ̦];îøÆ½ã¨QÜR:^ Hp6ø|Vàl“i‡äß ]UxPijðI.Ç W?õ²Â >¢¸ "ÈMA¬+R^’“›LZÎê"QxÉÛΆÃ4L6VB±ñšOvÿDi¢H1FXgÔ-4ÑcÖ¦€â ñA{±ryDsez?ˆ¢§€)Pð†‹™Áhkµ<ë k’ƒ×' Ç54à%,Uü3—ΓáZ7Ï£ugÝ…Yصª"ÁAxŠA—­Pu‰ÅÄ=‰ÖàR^t®Äñü$6^¿?H’NLè·÷—–ÓA¯ÈÝM{GÎ`]¼zbí0íS®áZkŠdãýöåQ¡0‚M3úÌ9³Ñ—+Ã+íùî2ÉÓï%¿×Hà 9œ}{Ífžø0SšóÔ…a\4Mf ©óùÃÔM€Å›m|t£‡†çmã êL6‰>©—Nj©ƒÛu/b6Ah|úÝÒ`ƒ“÷W2L»mÑ*Qæ§— 3!Òû2.éÏ aó‘²µ ys¼…=Çó‰6OTPðKQ 7% ¼[ÛÅfo•}Ïg  U(/›4|?Jò“wуÑ+À{J¸ù%cEÅB4Ž ,·:GÈ1•'%Ší•:vfPƒüÉ*â:IfXY;¹Ou¢¹Ã@)v«OV4y’ŠO‡çn‡’š‰„ Ìƒ² 4×C(XØÜÑÊm¼à‘ͳh^ ×»¯‡ü8Uä6y/Ü'Q,ÉEÐì§‘@Ó_g,1ò¬ˆR®ƒ IÒSNî× ©X³RúŠ>4Pܙʅª’«}Wh“匭¡UI_8Õu*Î|Ö¾D?ÓvúvÔ-}B(޼_ÒSzú 7)ª.^pzóu9'ÔóY*в¾QTGYhYzyË…¼pï=%«G·Œšs€¢ë%ÏrÒ.¡÷H›r~Õ¸¯I­ÿŠRËÉ~3ÑÎÐ.\F. †*E®þ ol:®ªQÀ[V¢qsõÒàs¦ÉFŸÝ±Ö™‘\M¡>̪q‘z>hë ÷K8šÛÎ…ÜæZÛ¯¶ÄßÌidþèN¶ÂïçÎÉ}?n®ít6ÁiÒÛùËïGo/í31L„¼ã=àaˆEE‰"½±Ma4ýušN/1aÛÁo™8„X8+¥™‘ÑÏèÝÕLÎgRÈñ9tC µ Û #ø´úe6p>1Œ ¤4ÑšOyy–¹mÖ‹xU†å†þft›ï€;¾é¸] ë×5.$æÂýYd —²†cá¾L óÀ¹/«-䩪ïw’ –^õhc/²pT™K”’íFÌôxØ!‘ôa}óé¼\|ÓX7ü‹ùƒ’[€TH¦Ï1´æKïª$áŠ6: «Èoöå›—_ÛRz$sßt¡˜S&ÓÏLÙ¸+X8eÚE^oÁÏ#š,¨~—{`*Ó!¹èVïpM$J:¶ò©qës`P„?ÙzVS[5âF¸Y÷Ýi–EÊ ¨ˆ¨ˆÛtŸx|7Ì[ÔÎæ©g—/­Øüu¾ŠqÓ^…܈ï_öÌh]²5¸œOì»a”t~"F¡ù)`¸boAY«• Jj³ôyÜEº¨ªÖø'òö§+¡%;ÌoN)(†¿OíÖû`»_v]„ éåíR"S! 7° CV-0ýr°~ÄòFÖNŸ•ÉŠ„m\ršz׈jâ[à’mº•âCñ¾øÏQ÷„6e?6_3FóB«âR"´Þòì¹@ÈÔY cx|û$NÅ$9Ê;Ù†¹ªìS>”ôY²õ2…7‡/ÎßniÏ5ÐÅFN”9QkÀ>— ç¿8à8[(¸9íÅ,ªJÛó©P‰¹ß8¦Ê2ÏúM&E~e48Ù†êj®‘ †° 8¢¼Ïhë À.Ë ªù Œð¡î_]Ú0ŽJ©ÚÒi«asV÷í8èÿ]…¡˜!KÑN>=y$ž•†™×Þ/›ËÅ•%?4-¯i9%|ÎäY—ÖÇP…b¾Þ̵¡Z"ë*‡ÊYVhÓïñSuzó4fÈ+iK–ÿœæ%䆈þ¤Q>ƒ­ ‚"ݾ9C…÷/ŸÝÔ<"&eV€²ëŒé„ùÅc-îCŸÀÊôBMMþÔçÔê›^Š”R¾ƒ•ŒÚk`µùÌž„W¦QóP³`Á®´)ˆªE ß;dGÂ9ÐÍ„ =0[âË'½]º ÖÁã*abOÏŽ]ž«9ZŒSâBKÈ”/&Sòo _·Í}Y7S2OÆJ†vI$ËSP«(Íåg ç‰´4Õ_}_î›[´£ àæÉ­'†ˆ¥º."¥ÞaF&bˆ ›"yÃê'¯ýãwdZÜò‘êõ×HáÈ–¡+W)E-ÙÓù‚Uq^ ÚÏÆj{¯„«p²a3Œ+è1Ò…ýM#Blì5Aä©®c¡œ@šKIW§í´½­WX}lÀܪÚ(¥mò^ý·êˆ÷^òoç”úFO½“  ÄkÒ.ø'Œ à—,O?ƒe7Ÿgî:<¾lãùB„ÙˆU€ }» ú½jÐö¨Ñ ©FÒ•ÝP2ú¡q™¹äÙ…1jþm+z|çn‹íks•]¸á³˜€¯í/ó nK2‚§²AP}¡ ùG£%ƒÙVIÙ;^öoPEîC'í{ÒNŽÂe¬æÂ_6µQ­\+úÖ÷ú¯;g.NgÑ´PŽÄnïxb£WÌ¡UŠÁ׉Â.¨'ôqtÔ;mÆE#m–;Sܺó¥®ï0ª8ܲ ¸Á¨j²åÆZd{î#‰MŠAº;`‘øŽCA…žÒT)ïÖ(ìr¥Ò=¦¾>–„=dñ^b;èêS}qîíÚÑ´¯•:<“SEƒYÌÝ×6þËÀü!P#×!0<ˆÊS"Ì…µðÆŒ+øçŒ9ž3ÏFÆ—ùh%Ⱥ5“(F³]ãâ9…}îx½§Æ„øù^¿¬®åŒƒ±Ñ|­GkF„ž #ö}ý=]h6AB§ïÛ…9Ǥ1ÙÑ y#ÕØê”{ÝD&¢E ´p9ÐËÍP >ƒ_È ŒÊÈûŒR Î×»Gœ+ÛÜÆÚè½|¥IÀ\xUÝ.S01¡]íèÚα'^.U‡íðš¹±8¶˜0Þ‹‰smÈ›IçëG×zò\o©¨œ{¢é¶¸{gÔbÑï‹c+“ʘ(È\¼Î0èv”Ú×g¥©ŸÝø!Ü'$Ls œRÿ(ºI—²‹Ëk+«æ$9ò Uácdqy•úýè¼_ðü™[Zëw‚yayÖ øÎûÔë3-úr‰–øii Ê0Ãñ6qÏt? ̪*'RÏŠ6a ̧CÈ ëUDŠÙeáCÚo¿Â»[ÛaÐVÐøoSò÷É8ÜêUñÔ´Q¿’®âTË¥¾³M–žf‚LQÞÞ÷?úK`›iHÊ-ÐÑ`9cVJ¾m0¶”;6ôCŒÜZF "W>>êVz‹•»!°ÞÑ22så—„¬©ù4-öä;ÂÞ FÞý¶[gb2?}RÛÚ´}gJE"†±¨ ›㼂¥&$)ùòBFÌuÈÞÍ‘NÆ«å5#IÜ?éà½ÞÌ'‚àÃó¦Ãöø«Äô¾ J¹Îs¼+¾N§Qf+³›ðz¶Ä±Þ©ŽóTX› ž­’·¸ÈÄC3 Œæ+¾Ÿg8ilöázè×¶BuPï\äö6êØd?‚³Ûw¡èäOKð¢Ð)P”Q¢[•GèÕ)(÷J_KÍOüž&êTã9Z’¸À>Px‡‡VÕê]gªã«¤n·ÜÒ\€ ìd3o•k¶Œ]eXú®Fm  9CObçîûJ®£Ð"Ž9- ú»æ^>ZØèÕ7wÉÚ1«×´äröö¦½Ín‹-ág˜éÑ®žãI©•Ð8,)„¬¾€Â! ¯G”|°v'ðÂ3¢aø 6"𳄛FšÉk®QÄ{ æ‚U}ÅëÇÕˆëžD–9øørQÈ­ÒfÙ(µx\8ò—õâ¬'wêêK ôˆ1LÇyž-3kÒâÖš5ÌpKhÇ!øâ¬g{DúV¡8YpIÎØ]’*åé0°_Oûk/gŸ/¾…r?TÑ#ŠyÌ+~Úv”ö ³^Ä.\ªÂ³ ðãÆ/è~7k^J|‘ÉÒ[ûŽEXõéËôt'àåÙj̥˚yæG¦ðÓ[fuÏLõ[,‘(ìuCÈT²ÆF\\\ÚK¦rpƒîÚŸz¯Ï'ˆ/+«‚¦´wä[u°g ík"ªìÜ¡A½ßA£+rHú²¾[ªu¬ï˜”kÂ@­RÕӢܡ*©1#¢wC 0ˆªúµ½ŠùŠC)°Ry…ͤEñÃ}áè­ ^zc6×Èã¯Y²lx4²ô¸‹ëšÅªûJ‘ÕÂ’”AXkOØß§gÇÅ/X–¦¥”8{±kÏ´÷4Gèë%FÐÄåãõ3†E¾îä’¡è_±ó)·þÚñûni°M¸{4~Zë_8Dº2ämVâà>LbõduLdÃí”8¡îmç5æË¡ªïd¸{†øµQ С¬æ \¬ ¢[q¯h_ôª©ÈQÁ`öc» Oˆø`1õPدû@¾zM´™—Üem|!¤ò—*m‹f/¢n z>ñá󤔩ɑŸä#¼8oLáp:„Bê¬DfÏï=3û‡GËA±%OPÑf)Ve»}¸ñ€=ºq$K],Q DئÁ\«\Ÿ··àQƒ3?»$žè@¥3o+­,sØð­v¤6/cÉ,¤Ô'ƒyÓæa[ˤ@°À ^up7¤Ÿt$«¶;ó&+{Ž¿š¾hXÂTF«]´áùg‘4(W˜Ç 8 Ï?Ý$Í(J9ñ*á/§´¬£=쇎–e›¾Rêþ¨`¯(—ºæiJ$õ´w«åªqM¼3¼®§9kÔ¤:r´P†ñ©ãJN‹˜ù½ÆØ#”7ÊA¢”á ”¯þíà“è1«8œ”–¼à4÷ŸøŒÛæÝ~‡á&‹ËËÖß‘„TãAÿì—ÅÕ žTey.~¼ŽÞR½Éd3EI9:Ï+3ÊšÃiÈö•Kˬ~ŒiÓÎäw/û¶FßÉ,rB;OcVÑPÁ«XÜbÉ}/4"Ùf×5Þn/Žàh;£ð–_Kÿ¶S÷wÎáÐ×òS%„gý¬’/<ÌûxBZé#¥ûpÏ•úÛ]A¨ bÖ´ßÞ1½mYórN3M/ü( Oj+Ÿ³°9à@´„AÂ=ÂJ+žµ¨Er1ŸðoV’ޏ÷­z¾~±®o£„‰š²Ž[Æ$ÀøLÍÉ8¨0—u!˜°?Þgþ뫆T‰Ib«Uo¿S…Ѭk&¿ýêrKÔŸT!ø®cH¾â¶?H+Y©gÆ—Å“6FOÑã¤ø!NPNÞvS×c¯ú3ãØk²ø~½‘Ø2ìÆºØeîŸ(LMÉ5§Œ'Jt:W"Ž©çæœ·Ühœâ£QiT?Î 6>ß&ÓAô£(P]u¹CKAÉ»w³j¿?«-y¶ëuAý¼ÛÙŠC 꼈m×”HëˆVà”VUæȄ鵠b{Ê’Ø \l*—ƒÔB“c¸=}”-ËoÞîZº:)Îf¡u®éPbÄÌ2îÚŸŸð·MÅgø ÀˆFȆ#q¿B:þ€!~²¬2B4FbéüÁvñ¼ÔÎ6+Â×㎨36óåFç°p·î¼\ø̰ãÚ½XM›Á ÂN½Òb;+†þû×ýWˆÈNAþ·gP™.bUð]Ž)Lü¸Y¥w vË ‘r™”3r“"ßú®‘âÝàoýšžH¸„É¡›«z{7Tëü8:…Dô{& Q´‹ªH\% `IÙ´ªx#/·vOÆ)¾˜Ãež¾êË)NÌ[5úsŽ!Wä×îdj:Lš£Z°ß(Öp©-¸0 _[ò2P`‹u2“”’ÎZ}¯ÒÕ²ÕBhʈý¤êkÛà…=‰Kfló¢ÆÇ9ÒÈ`R4_œ!p"j|N„ÎF™¿|;t&à GŸ¬Z|ûüÒ¹¬ÏBìÑ,¥{4l§ÌOck6“®ä÷ô‰ÛÒÒÍØÅIQ²ÔÞ¡WÙÝyÏÖÃs,É[Uÿ W\·HŸ•XŒDöH~S¶•»8ì´±ל‹*ücÆ¡çÛ˜®ãK7‚Éoøa}¦÷•PqPä±ëò OµâÃ=ñ×4á­&Ü µëó«a¬ïüíNº‘Dˆ\`Ûݰ‘Hˆ»oòA…g¨‡Ñ’#]ÑO¬î.>cO®w¾oÇt#\3íä³éSq…Å™`¼KTwUdz"ß$u£ çâR aìâÒ´tÚ+aKÓµ3ÐýT¬Ûî®æÃ«ÁçE 5ÂàštRgíì‘¬Î»Ž—n!ζ^Æ€ÅáM«§uBKV¼å(èfŽhÆöêœ<ËøJ¬ÚËð¨XŒš­Ã4u*ˆßJ$F'“+˜ Ü}‡¢,\<E$ëiZ7Ãôqê¯ù|ï“­Ä–2‚“ó0ɺz/Ê=ˆëUwV¬":ˆÒ„Qwy§DÙÐIqÑYˆþªdS¹ÄÂË1«Ä ìÃ\]¯4d ñšÓ€.Q “î»g·¾^Ž ©È8ÜT-(H±‘0Ä·A|AñØö'¾^œ!õÏÙÙ»‚ÔJ=.u·ÉŠäpbêµP¶qI¬+ê:ƒLLÛÏ~§K›\0»&žÆÄ[•ïëÁñ„%‡0ÿ÷¸+!¥îa¨¦žÌyy/*ðÚþjÒ÷Ú ïß´ô2÷îS4jM·9=VW~>èŽ\•Fá÷<7 {•Pd«ÖÏ/m%ì'Í”Ì Ïî°XÏ5€Hödî j¯È2^xC*lôC(CHŒåíúUfã©t›` nd³Ôl÷¢¡ÑòÉ*nÎSÛ³£§ÎïgÕöv‰i–´Œ˜áVnÇ”í>Ó1TÅSžy„Æ1#E]xÔ(ðüér}W$¦…ÑìA~œ•µ%N¿pWããÞ)…Ayê¼ÖÕ¶+xÕŠjã„¥õ&N§E>Ž-*äˆ‰Õ ½ù;m йøÆ–YE;½ÈG¨'ÎÐɦºJ£Ë:HH•M°ÔÝw´¦ùvhð®·Õ&‘·‡³M2‡,g(v²ñ¡Íùk¢Ó $‡ÄF¼ô´AÀ½W18ãO;ŠÛÞ$+­ …ÕFì1¢ÄÿO+•zR$ÇqYyNº|Ά¾/Q—q ËÝÜß^Ut`ø¸öP–H!,²Sšœ°¼×“Iøµ1S™ƒLÈ™6€…›Cádí£ÃXm"cƒ¹ÚÊ&zê¤\^—åf¢*Ä·âØª/EN]OK–+ó¬²U‰fzÜ­t8ÓÝ”ÃO¶£ðmÈWØÝrÔ¹ H -$ï ßëv±×©“ö ¬×¦(æ7»Ô̸£~‰% ¹ÎgþÆÒ» ^ŒX&u“þ,€à…_.Z^`öÜ%rþsÿá ]LGŸ‘4gWÄmwê]Sž˜™j$Á¥q;¯ þ׵Ǹ'E¬(ešO^ëg`X˜"Þ®N‡HJXla~е~“VM=ãØ DÏ£a¢z³½üiXâoófIŶd©_ýÖaÛ“˜’¼ƒ¡ãÀ䥎~›Kg¥ŸGX®Œš¡×úy /Ý2ãÓ,»RÔí+b%€¾íï™é™>z#É”G°tñº XÑÐ=`B_×X[vOÓ «Ž‹·;æñk¼ù8­d€PË#=µuå©;W&OÚ4º'tyÐqh—®Ž=c/HÎVwêL4nŽ*6•vÞVÍr.£>H‡!è¹7¹^!Ý(¼Ó͵ÁògížDaÉÔk^ š^ë sø¯ô¬—FÖ vìã-I±”ë²×iøR³¶‘]Ç6¯ÌÎDƒN¾WÎ\:¡6k9~Íf Qæ—%ùê²âÞ¶÷ñ¹§¿¶Á!€Ä¯¨uDìAå}&­ZÜà R ê.³”!£ßòßé)Ò~¢9;_4uåmžƒµ®¿Û†È/¶-ÚÑXüU=`ebŠvH#=«T¶4ÝÂX÷ŸA‹Cí!~ú€üe}ü$9`7]3kv JA‹åÐè‘ó’ÕƒGŒ”8#¬üÒJ3C#×,¬ýÀdŠŒq߈ð`Ç”}‘¬âÚ‡°lZ˜‚qF‘GQÈçë÷¸läˆ\¯«š"Ø8¢Ž+Mû´:uj©‰D w.+¢LˆÓ:,H¼`»®×š„hºÞμKÑ˵nî£ ¢áÑŸäõÁg£È#WéÃ?e%ŒS¸jïU°Ì¹´Tï:b¤MÀˆÃãÙ^_Üpª#E×ô’‹SñÈ×#Bß+ÙÔÄ•#‰Ï/•A¢)ËÑg•u¼^Ô“r]):ßâ^ø&7Pí½ðšäA_5\{úË8Åì÷àÒD¾ì U4}sv%ÙqXa¦Æ¨„}S—Ç•°S²rÓ}&^s©œtvÒüôM:39&€¹rfwE¦Î'–¯âSÓ­lˆ ±tÆ'ùÜx‡æ@ *WGðÙÞ{zób(,òãO !¤„Y’#V…ÊïÍ¿y@fÏóØï+Íw©€3^ u !ŸÍê°ù³)¾8ðiôø,Šö3fÆÝMãP½iH>_Œ tå6à§&U’k´Œ_‡,"`É“f$à ¹Û×ÄA´¦c¬íãûb°^u?£ÀüÔÄJ C¸àˆžløÕP¾0úŽ› ¬0Atᬠ¨"hñ3}ºW\Üée¦3ÞCÑoÊh%{=þ"ÿ˜±9»øÅfŽTb>¤)@¹cÏæzt*×=kq]¨ÝÇ?B+73|+hú„¡'ÝÓy *íû¼nk={mÿPd½Ü²n?%—â<,¯¾ÑþÀôÙxÙA‰ÿè[c™HàƒžW'¿¨Ï‹‚ Þnˆ:’XÙ[­H=žñ‹6,Z²(H•±™Ý„¾•¢+ÃÔ~øýé+Z»¡*ÞøZÄ/™_zsd9ŃZÍ#¹è.:³ŒlD BBt¿Ã1S#«§M±?˜sq`U¢}/z+ª§˜$Æâíx¾"½EÑX'(©ßxKè³ë¥—Fq:9C×rÿLŒYËùíò–Å”íº#n]Se-^»¶z¥O’c †sžáíåí7Ñ»(¤GgFè¢1éæYà*Ëi¦›xD‘Y$§y“Fh2XíÕÏð!g*wü)Muae¡¬ ¡Àž\€ÀäcyUn’‹– BÌåшËWÌû}D±¨8Ä€jÛɽS>ò,X’ªXæ]ägW=HqÍúÎ탘ê€Ah[ ?¶oۜ˵qŸ ÷ѽK/åäí;GuÜI^!?ñÏí×ð‚‹ÓF󑯨í¨/geM õͯ|C¼ÞŠÈ!J˜üŽý  !Ñ“~ '§_½~Bƒ9K€ ’’Úë øT/Ù„4JPîÃi#è6ˆâXXß6¤¸¶µšFÝ„N‡w¶]IŽ“ˆ@¢±¦Ççf€ÛäÌoU^"=çY`Vñ7SUsþ!‡,3kÇ"˜M¢Ö²¿ÝMØ,0´Ô%>‰*†Ü¬™/8¥à¤&/áDèÆðñû~Cj[´!`Ôf™àÝë7ÿ~DÊr±b¹‚…\¡û,—”òÎ ó®ÿí=‘|¥) @ %•¸ÇRé| æ›fmñ,8Ž)}Ͼ·µï+;f~ V(ÃÆ¼gJñòF‚„¢7+í fÈ¥8*2¹‰îÄeê92–¯±lUtHcLãCö!sØÑŒ&ei^(£>¿Æž~L4Q/Øô©6Ü÷\°`­¥W²F"(_Û½åI‹xgï§÷›ûQãpÞœ¬s+~ÉÅPå ÁêÊÚ;EèNöúÑ÷¯’¶øré—-Z UÓ…0&š$6ú/<'ìÙe⇠?@(~-Û‚{”øÒÌô˜%Á(ùÒ²"Îqß¿[]µyžù´¯ˆþ¶ï†;T,óö—¦O·oÂÅžÕ †çhÍ|ƒË®ã'ÔëÞqѵýNqQiÊkáíšcmY¸À•×r<Ÿ¥ö,ÑåÀpëkX‘"ºËíô%«qX¡|MC»Vàšl#¦ÈÂñfÒ„WjÆÕñ«i Ș¾áx%Swu›fBAëŒzhWkQ7‚¿ –Ùzm‹ܯe~ñ˜!Ð1ÏÃq3Xrô{YÌ(•Öî #•;øPøµs„m'ì›÷i¼lÕkú4[S‰d*èöš«Ãt hqM…÷öÛ™9d]_èïHO¬éMö“äw³ƒèä§ø[ÖwÈ1˜»„ _(` Ë/¯Û§ð€#äîDp…Ø&èÖ«óÚ‰úÙбV,#s¬ ¹÷Ã!dæ_á€ý¨ïÚkÒFy¿´Ø¸*´ÕR;¡ÉÌ ~ì:´*âgxFAlË=ºAìÎ?ñ§óC|,ûÚ~¢23ä-ÐIÑvö2w¨Üv“~)x½ !b²°îCäYyg£‹Ü€à˜’E3¸‘¸ƒ9…¼RÔnV 8ÐÑûŒ2°’º#™úYAKYŃ{2¹è“žg¬#çŠgB4¶L„úÎÉŷ䆙jrñ›÷hp~¹5nB±:Û³¹ü»ïË'ößçzŇóù#J˜^g‚qS°uø"çäÆÂorŠò1³S—/ ¸òÄD;©Ë‰;ná‰àF$7,YZ“"âí…#ô]¿Px¶÷‘'Ê¥ì£ç»jÏÖæ 'XÔ¾Þñ&c+‚¦ACã[¸æ[‰Äfñ2©ͽ>s´KQ÷ë°ÛLQWí¯µy€£©<Ô ©Pd$õfè…Ô1’h6ê/à, ö Æcv׆ƒQ‘•jB†JJ•vúÊetÝï›}c“Ü[àúŒ»<þ…t¨Ë ´ÝÓ’¥ææ9>êPß&ö@À :žñ[oô¶~:%•Ï#Înc•)ƒ>•s_5æøÃ÷¶a4çÇ¤ÈØDà>nqÚúÍ\§7ºtͤϩ{šªK³ÂC‚FCï'öý䤣ˆkµU=½ê ¶´Ô'‹¹[E–µf¥&¢TSò¹íæDî2¤[1Œ‚±/ì*›H#‰áq8 I.´žß1Ñ™(²¡`lúœE½©Íü®õ; ß¡uê ³OddÓBŸ¡ØO’4†c®øI§è»­àd8Ïô(E„G &ü7ͰÊ,hÇíÎ×#-oî!¨ßÀšìª«+q[ƇÒ$†L0¿Ö­ÃÀâ_mnyÔÇãe© ·Œiä¥è¤¾Ë5Éy•¼}^©T´Ñ™Aºq"´+ÉKoàÑ×¼\¯¶ª—q¸ E…ð„×™Ö;Y1ÏnÐnÞbûd3X®¡ò•‚:Õ`[*ØÄÎ Z¾+Þ‰!Ýw0ŸôU„û¦´´ßIcÛÍÑïˆüþhzSÛè—Ž¸e,˜Ù?]˜(įâsÝûQE1*¢ì#S¤ì ·½Yc'ÉUÁíÅp5~ÒÓ3è¶4¦†\Ò„œçVÂ\ºþx¨!ˆÉ†4ö;Q–w û/š°'$X1¦HS冸•‹è;mÃ?ê©“‹“ù»wü¢›EXÎòU<¦í;üII *Tá©RÚ”mø¼I{÷CÁò‹<$.Ø:¹àuô.æåE „ø¸åP+?Ïô+¹ªùä]!xE·ÂQplŸ3R’¡º½0Y ©Ô¥+GÂÁ¯{ný겂mÃÆÉV/Dí 3 uyS*Úå§™¾£§"}Ê ðq­—wýÒÎõÃ7…OP¤ô3ÆËgÆþ@ãY×z¼¹¾þeM–¤çŽlÁ£ØØCPåø€»Ýãê‹KQ° Ÿ-]8#h6êÚÁ5<$~–dˆszÒÂJ%Dm¡ “ÊóuB1t>‡üP.KqøíO)N."Í«57 j!%6CbËIÞƒe%N+ðc`wûN}.»ìôZžWLå?Q”>Õ:äÐÍâ?uÎU7!…ø©ë)×&Çïuj°-Ê੽Ö&iÖ=f{¾¾î,K;„ð)l¦÷…S÷½œaˆ¯îö˜?_×.·½PÓÞ'˜ï°÷ÃinÌJtG|öT aβaþÖÀØž#ÏõM¢˜RK3ÈBHD<Ø9ó„“nèÆ =Ö4#Ëß™ª¡û<ê#yþ{Χ÷,Ëâò{'Ç8HžE·a%zU¾‹³Ùâ|?Ê›zc„XŠÏùÍd ?“-*ßLüªäÐOÂŽCjl6R 7Qó  -‚f·ŸÉ]B³:÷+0.ò‘/4Á4èi ÝIÞ— n!gõâÄ'5ÇV¥T(Fi[µ§/~÷Š=¶D¦h²u+×D®>LŒ¹:WÅ;®Gp¶KZJlùL»2ñ¥Z„ÝÒš ÞgóxëÀt¤”3ñ×ÐñÒ³'+¤Ì…-UË»b‡C9–Þ`£Š0Pb“yµì¢ÈPÙ¢9 —à&_lGÛ•I–Þ™€gfà·w™Ð瞬(7n;q÷V‹¿}³P"­xçB"kÖ>ë¨ãbîk½"]C)Ô"b"¨£ŽOÊq.*‰ö@ö<¤üÞkµIù¦Jb&Èûdþ’×xÚA$äk_lðQfk`ñ÷!<½q‘üz–»†¯{›QºÝ“‹Ð‘ž[xhr+úš¢Ð‚šË×’Y£€‰Õ;l²!„úÃÏ‘"¿ôs~*<$’±c§ú`›ÊëY(7èËé FG @`עǫ²;{ÐE¿‹ïs°ßH"t[ÿü‚Yn´€ÊGÿUSiË„7lùy­žå•0‹ª˜òŠÆÌÃû;Ç ”• e×¹õXm‰ôñqæ®Qºà!oò{DÏÜ ÊÜ6øWýUºª…ñ]Mzz¯…wµ{¬È“åÓQQYä5”ñ$c#µ"HlüI%Õêš¶¡h×ÇZçÆ¾"Õ)õHMêÖgàó£^‚åS-»²«D yùOŽ¡np‹‚Œµ¡YA{O÷oÁ¹»íÒG+?âLA'ñ=‰£·¥&‡x•`ë‹8üC•ƒèãÂÍØao~'}UF´­VR}Ù±;Ò‚‰ØºlL1Döµ¿© ùr¥_d4m}þÒé×ÙòM𠎀& Víª;G¥gœÙLgngü¬´貎ŒÉàHåˆàý‘n­Ðœ„ÜŽâT>±¹C cãêÐÀ7̈Ò.¤…/£Ä’ӭܽ „Å»ù0ׇ“AHÑ%¿Gêý?í×KE±‡6çûì˜-€ê°“_èºà†ïÝN}F²àbFkIÉ„ÏEwy=Þ™Ä+ô„.–͇DÀ­hñl¹QëR…Ëõ1µ¾¢\h¨)p±Tuyêô˜pž‰“Ô±W¤©õ6RW{Œ[§±t&þÐWWæ(½´ÙŸiú8’fiÛíÍÅý™í÷ |¶µ®Œ@È;3Bþ!ßúW âœðì(ñˆ§â³]øÓG>1:¶ úM[cqrЦN‘9]ˆŽÅöäû±ØÛå¼UQ&È:uÁwÐ ÞТÌÐdñJynU½¦’î8„U¼ÀïI˃ïÈTr¢5ϯûÄ(…'L£6`lFãÿºˆ p دn¿µ Ã^4#¯wORï©ßñeË`}™‹øílÂs7wT]’·¿;®H!R0ƒÛÞj å&[»J¶`M åÈ‘cy¿«Cˆñóiê]»\õ ¤TFŽåmÕ^nNeØFåsTC†>‡‚Ë/ÿ¢.U˜©•ô|=á›6Éê²Í^=Œ]BF1Ð(t£ ¸3AV‘ßi'«’(%[ÏDáœÍ%{´Ûrk1ýNôiËí÷“•‰wjäD†«Y¶iI‡-‹7q›º2ë_­¼ïp#9eÑÕ£¶øÊƒ mäŠ~NöOÕ­— «—FÐÊþ8\ŸFa¸–BéÛ®#M°é ~nƒ¤W¹)¿µöƒdê«1¨¢Æ2¸ÚÊÍÝ“ó-ì‹¢ Z¶·óNS³ n#•é0Ú¼ ºëc¶y¹ê@{:IO»¶¬ÄD3µ'¦û#°ÍÐÚ~­&°!­Üï?쉵›Bp¹!Í ³QO–O\¢ýBÛDãÛÕ"µ‚XõØ8¢ÝtÌéÇÂñ†09Ç=ÛÉÇžø”7›5ñm¶Æ=rè³:@F/ríB\o&n8/ÅÊMÊ„!—ADûÕ;GsÏŽk\™Ü¯Ûbp2ŒëEà| òrKëš29€—Àõþ¬qSËw:NjaÕ08Æws´jyÇÖ_Z—Š…ÿéþ­qÅ«É`Á??çNw a1¨è¢)EƒîĹ)> stream xÚŒ¶P\¶- „à.Á4wwww'8Ó¸Kpww'ÁÝ%@ð`ÁÝ‚»k×™oî$sÿ¿ê½¢ªéµ}¯³÷9MN¢¤J/ljg ”°9Ó330ñDåU˜YLL¬ LL,ääj–Î6À‹È5€ŽN–v ž¿ DFÎ`™˜‘3ØNÞq±0³˜9x˜9y˜˜,LLÜÿchçÈ3rµ4È3dì@@'rQ;{GKs gpšÿù  2¡0sssÒýË l t´41äœ-€¶àŒ&F6U;K ³Ç… â³pv¶çadtssc0²ub°s4 ¦¸Y:[T€N@GW )àwÃ#[à?1 Ô,,þ‘«Ú™9»9`¥ äöp™àäUi9€¢=ô±Ü?t€s`f`þO¸{ÿd ú—³‘‰‰­½ÈÃd0³´%äœÝéF Ó߆F6Nv`#W#K#c°Á¿*7H+ŒÀ þ»='GK{g''K›ß-2þfYd*jgk 9;!ü®OÌÒh¦ÝƒñŸ“µÙ¹¼þ Ì,A¦f¿›0u±gTY:¸¥Åþm!ü‘™ìLLLœÜl ènbÁø;¼š‡=ð_Jæßbp>^övö3p@K3 ø‚—“‘+àìèôñú[ñß™`jiâ 0š[‚þD‹fÿ`ðá;Zºt™À³Ç `úý÷Ÿozàñ2µÙxü1ÿ×ù2J(I‰hŠÓþÓñt""vî/zV6= ;3€›‹ ÀÉÎðùï(JF–ÿ®‚é«4ÈÌÀýO±`–þ§`ן?Õ¿wƒðß±ìÀC Pý™ñLìL&àæÿçIÿ—Ëÿ߀ÿŽò›ñÿ]„‹Í¿ÔTÿÒÿÔF¶–6ÿ6Ϭ‹3xþåíÀ[úߦšÀvVhjébû¿µÒÎFà=™Ûü‡FK' Kw ©’¥³‰Å?Ãò\ý÷’ÙX‚€JvN–¿o=3ÓÿÒ7ËÄ|s8'ò_* xqþ;¥8ÈÄÎô÷†±°sŒ<˜ÀƒÄÂÎðb¯¢)Ðý_3 `dÙ9ƒ]àö|fvŽ¿O”ƒÀ(ü[ôâ0ŠüAœFÑ?ˆ À(öqÅÿƒ8™ÀÃ÷1%ÿ £ÔÄ `”þƒØŒ28»ÜÎ.ÿ³+üAàìŠÿA\àìJ8ŸÊΧúó©ýAàÞÕÿ pv?œ]óg×úâëŒþ °ÎøWfòÄÖ™ØÙ€÷$ll¿%¶¶üŸ:£é_ÌðOpUÿŒÜ XÀ-çÀÈÉâÏiüöqpoÏŸ0`Ìþ@°Ù_ð·ÒòOÖßÐõOVæß‚?Á؛۹8þl`þwõ§60¯ö@Ð_`™å_Ü–Õ_̨õ_LÛß­€9µý«0_"³ƒ]AàUùKîÕîO1`g»ÿRƒ›±ÿ£³?€  ÙŽÙ˜ÿ-uü/êÙÀUÛƒï,»?ÇÅ&ÂÞÆÅ靸`‰Ã +8½ƒ‹øBùïCd3öŸÌ`zþÄ`;9m-ÿ{tØÛ]ÿb•Ä üJü§0N633¸ä?iÁ÷/£³…#ð¯ù÷ïìf÷—8†Ë_|®ApenØÛý/ïñ3íù§8p$O ã?©þë3qqSíü¯W<Øÿƒÿõ“tš ,ÎÙ™ðYÕuÜ׸ÑïŒóO“ïh¦QÓ{-:vº<¢À&SWg¬;Þ 'C[Ù§ºZ"~ö:jm€ mKTnÿåýd¯2¹ÓްðãÝÀDÑ‘p}?!ü{z5¡]ïgo ë7­]2äy.\(J˜÷n}’îõýeË£!s;ʻղˆOeSôÑêQý¿ÌçgÏâ’Â8ÓÂÑ`œ»£ÎÜÜNcäN¼ËÄÓ"øG³{él°Ä<Ìz®V¨±8uã‘áéྐྵÁ¤ðÙO‘Á™÷*)^wM}×9¶i›Äl³Oå¹£ rïxp©OA>ÁC…‡ËøK:2j½M*Áö I [öùŠÌº»ô%g«±b‚å«¢ g=» "÷NÏcn½ç>,vM¨Švr=1¨—=”2·ž%¬pÇ|ð)gíã Éê÷U¬ÆnCqÂÖN¿ŸæYunþ«j$Ã+îCÒ32žSa®[46Xç×&™v]»cN¦¶xúÉäüû5mɹbˆ´‘ïê³ ]n¹[ ÞâGHÎÊÈkemTB4ЫÛ9B¤Î¬ÞoïwC¸ë?ÜÂ*S/{®®ÌãÊB/‚—‚yh† Ýsy'ùc“Gl #tS&,æ…*¤àJ³òÛը׫3½Bz&>†2sUT$›$LÅ8¹³éüv}î†^¬ž/²m4o½O%‚^½zÃK¡~esâtëx9¿: p:­˜ôSÝRê”û_(µzN>‡wXâ! óâyè +Ý8·@o@½x­]X±ß#böWÕ¨ô‰äùܽVfteÊdÑ7ïõéŸ-Ì,‹ÛÉhnÊcv°9û€ï›€”¡3„‡À÷Ü’~Q¾'W3Ô|¬ª“¸ÈÁ¦]åP2½s8rD4‘7]äÁ[|n”ÌyNþWú b®…MQ9hY ’} ª w³Ó¢„wžÓ™¿²U#寉©C–ù†›£N]Ÿ•¦-ü>ð1KP4ØqZ-jï’¸3w©éÝ:yg¼aµLë rÿš˜þ 9×V©œÚòq+–‚…ÃËÐÞlÎ5çnâ 6ÚúÙü‚P¾|âc»lÅÊQ­ FFÉŽûT¦ðÔ„ÀÞòówY¤žtÔƒTΕo‚Êiï2Ù útúf¨S_ŠhñÃm•û(1¹96¤9a Œ¸v(Ų &I‰µ˜ /¾·d<ÐN˜®ê‰¤`M! &˜1òh:þ\7©¿Ý\f{Ãý.ƒáÀ2™60ê«Ì[÷j$žžÂÝ•‰3m•½ óÁnßêÎ6êØž$ez”¡Ž‚¿ï×ï½ãfo'© į%{º„Þ¶#¡ƒ¬3}=÷'Ký…Š·½k[29Qõ¹Ô9ãi塺}ð0íX„êá½üÏo=΢qÙo°í“Î[TrÕïZ.1)™:ÚJ0ã(Sè72Kë¸0“'¥_…ÝiF É6IV̉UÞàJù©B¼/çUéÑ€8Qßð;$±ù-¿X1ÉbŽ©¸¿Ì€¬ÖÇ™ˆûØä6‘ø‰Z°õM±(Üz^І1§þOëÌœÒÞ d…î$š+äÅhÉ÷ÝŸ‹6½3fz‰ÂÔ‹^MÆªÖ öQ†Klf>m&rLYdp¼Õ…gY\oü‘GD¬³áª~ñÓ¦CÉ›œZc°Åö¼m¾<›ƒŸ¢Ãa¯âݵLL¯SZaáh]Bú[˜O‹øÞ^*Ñ} 9ßSERc9­¤ïðaýqBý†ÒXRñŸë°ÂŸ¾#½¦ q²! ½B`²Q%¼ï`à‡<ŒæLYPÚWLmѺ'»Žiù„Ô FŽ¢Kα¢‹ò¤è7Å6æOçÆÑP´²]Ø/8þt~Úd¾!ʋշ@Í´ºP5Ù!µÑׇõYj¢wàj›\¾®Á Õ¶¿|†ÍköŽp“pL4Áâ^W¦ÚÎá³æj‡­æM.ã”bL,lfKUY’ÂmgÿZ9í3·£Þˆ=O'ñÞ{Œf%0*è fE„ñŽ}8 n ‚*Ò]ŠÊ·˜qïwúÉ>yÏÞÙ’C ¨uNX×lÂ8º×h Ƀ"š]Æ5 ÉñQ•¹¯Ý$YÍ ý^x;M‹aZVl¾ÛÁá·²<#%ªo^ݸtsüL‹$Çï×V»¡T¹ŽÄ·š‚ȵ›c&”/ùȽÄÒBœ'ò(¾42ŽÞ îMçNÇì`C`³µÄ4”Ë  ‰ EŽ‘•kÍÖHaà Ç2gz'­œ„wÅ·Æ “úËÕ›ï„vFrq[È9ÚA+$J`s8Ö^§’¼†ŠHëÚ5ùû.§s7¤M¹pµìR•$1G1:\JŠ^bmÆãF­Müµöe ÞÑÖCk5¤&ªªR½œ^Tv•zÝ*ñÊcaV'ž·@á‚ÕÂQ¤·:/eCâN “Q¶ &?Ê.–B¿…M_f (w…R´¤ ºWí¶z‚ÒPºÂB¬EKjÌ4铟9Âí`iÒìinÍ­ltò‰,œ bÇYyXŠ/=($ÒIÜønˆÏPNjÚ%ä§Q¼pK7y3„™@Æ U‚®}˜Ú ã´2©[Õ˜ýydÇ™¿âø=0?Ø£ÞMÔ¼á^[Õ0¨m'#BÜ„âîS”£‡ríÌäzÖögKÚ…qwÎêãT>ø© aº‡zëè÷£~u7š7«:n¶´}ÍŠfc#`4®Rx=¦ÄO¿}#»üu§ýâò Ö¿\ÑbBFx0=£¾C@ÿ ·kîtœ ,¥´­sËt©Â‡³Ô€Â$¹i‚]#÷¼^’à'S’NDȤÌOa4y0þ]ÛÜ»y8ªUýb¦˜Ö ½ø Æd5ƒ!eúÎ)l>ìÀø5)…0Ç>©Jéb:ÅfXÊb¼Í t›‚zâL„ ×ÅCÜ¥îFðßÕrà4vèÛ©šId›u¾zh­Ãw–èU{ίÍ34ù•>`#±Ÿ„CLÐÇ&ŠÉ5°8.JíT:˜|©f$rÜû€¶o>V­Džé¨0=ìJévÏ›~69êOûÞ6‘_ð¤mºJDÓsomjVP ,ÿ¨dB*Š=¨v†NÐûÐX>`cN1< ,I­DÝO1f7Åœ¤Q‡gC®UW³xÄ[µqíân'0 †|˜Á%³ÍÌ8"D£¥j‘ŸíXRú¥™ hŸÿ}ÐÙDÔ°m6ï'SfL__{…¶0U?åAB³L"5~5fÒ4ÿw ¸}L̦‘zAÄÇê‡CJê¶E¯>²ÚùÕ´¦sú&k‘Lâ:ÎtCÏX˜xÔ–·o€ŸŠÄõ•Ó¹ì ôÏ–\"ì/4»A©î N!âñ_PbJ¯my@2,é›åcýÐb·¢v™ö}~õ‡*7ÁûÞ͆ױÄÞçMçÆìw„ËÝ$Ì€Žé>SÇ:¯â'S¤„-ºÄ)¡K=Ú…¦øÎÑeTÏÖºô“ʱzU—ìEÔ{:ŠYÿ¥âšø•q+Û? ˜åDjÊ'0>Èl×A6žw_½ô^´Úãà0a° Ƶ‚e0Ðãe9uäÄH “¯Ív¥™KÞ ÎX9÷Rsñ0REIçHæç.ÁÂ@|oäˆ„Æ MCæ ¤Í¯+u¼Üg¹ç,Xùð‡5|ªnçîÚñì•þJýy É(©Ð¥¥`/žÂ£î¤gÌkIM/dzuLj]±T5ji´‡Ê³õƒÙýa0érhÛ0F£;ù‚B\*×_°É eî It9u0“³ŽÞpp‘ ººRÞuöððw}0…S_Ô8R‡IŸùéD¨n¢úv?ˆ*Èt1&ÕnÆŽøî‹Aðq’ Êßj{Üw”Ñ”db󶯰o!mÔŸì\‹Ÿ#riÑëI•É=ùûÈJÔ! ]øš±e8T$So¿7¬Œ†ºÚ®m×ãß<ô¶çÖOaéUð+‰ú=­°¬ ÎX?ß`aR @!ðk%9çÞK§ÜGu2)›õ0¶ÅßÂGü"Æ[?ËÌ’¨þôf‰I”øÁ=Âöc幑´Š ½£öµNÎ]”§Žü²¬" ú¾m]^ßçQ/ÄTNÄ¥…Ê-m¨Ÿ0+)Cƒz6óU5šÉk_Ô}À®«ØR!ÊOVHA(-ê+íάºo{õ!e­¦è›åœc>çäÛò÷˜î“clÅœ‘'\#Í'A~µ¡CìÖ¾³Pq¡L(pÖ\Q×¥qˆÍy÷™äÍð½~I°Â'FªºIì}Äj™N`®=n¶ÌŠýJ²„YÅocTÐrEP ×ßîø§¾5™P÷V¼,¡mU'$kpœä_ «"Å=7챎&Òml2Μë;ò² âs_8GPÎR˜—Ô±„ ¬X¿ËŠ7O ±ç÷ ™6@Jgš‘ ipÑìœ.öôÎTmØÒ–ߪ6£Y/ âø† ;j²Wµ¤Ï—š¥Â>æJïVE³#ºöp• QðÉ2Tp» @FÄ,8/ûˆPå3¬¥×¶Ô‡6 Dª`È<ó~ß®¯ôs1ó‡ÁcXB÷T>Ç™¸Oá»ïÔ²`ÔåS³‚”*k ÏìgÂò =£¼^(3³ÂÜ‘Âϰi3FpøNùœç¸2{F×m¤¥óV²{ùÏœ€¨5£?G¡qn?1ËŒ—•ÒDÏ×t•Êé¦7÷E;ј˜ß-øÚZ›¹–ˆr­~Ä AFæV³×ŠÕGxó%(Ï’Ó¾¹œ¥)9@Y®¼ž³®È¾¹ù©ÐµŠ^Ï«…à’®m°½à‡c÷ÂT&:h·]A;ÏúËÌæ8éŸ. "R¨”Çõç18ýšeØQ$Z3À ­ö+ÆO>N÷cÙ'TË>ÜÌá'LÝÛN‹ia}0w.oÃw¯qöjœ %‘=Â>áˆ^Ê@äQûS¬wÛʇ“@oåvÁf|„îêù1zÉi/Z‘W(÷£XF¤•éæý&SÅ÷¡Ðö•ƒ70¦ÞUé'5¦dõÓÖŽ.9j™y¬¢³ÿ§ØÖ-\³akØŸùÃs¹Á›Ä>MBaÍu[¯oK¯4±(öJ¨ß~xŸ÷«ÉˆšûE›C6Dzki^*’íé }fø^Oô`PÏ„vßÏ2ª-¨á-Mà÷‡Æªy¦ÖŽ»üùcC/0vÄËW1W¶m¥tÅjºW0…‹sFAg”ýŽ1K_›Çùióœ §è(ý>S¢^ºúñ%Ç‘f}“M3Ø~ž,ñ½º!}TSÉd€H8Á 7*ßa)/½ÁÈPqÔÛa+Ü4ímþÚæ8ëþ›éÞ6²ÍCÆ+ï)y•ÇfzÃ(‚j¤R^Ž]ùGïþÜ^sßK¿;m€K™n­Í%•]Çâ+ÌŒ¿9~º8ê±[bsKÏ\­_Ô'ûkÓ¥z-¬X1-b¬‚IÄV"cy(`%òN8 p~þ~ÝReYË«Ux?U¤Š‘üQ;&Ï#U|zÕ?óÛ›ôoVOjÜ̸gJ‰_«›¯õÔ¼û&]˜Ò=74å#T÷økâß\ Wñ§¬32_ú¢á€3ÑtûÑ}³÷ÄÂ…sÙ Ö ŒÆo¶öë\¥Wïv‡¡šßä+c¬a\eCŠÕÎ^ý²¾wJ)°hÊ0 ŽÏ5Š.Uª¡òµ"Wª i@Eh”Ô´I–óŸ„JÏÝn<ø| ½_JÑaárAÑI$ B†=CþÃmòQ ‰T’Št ©ÿgÙÃóMcÈæñÛáî¬ä)4Ï`è÷Q¹©´¤‰Û~-XK-e?¥"Òn–ð£™%—rï¤Ü#~j£v¨ÕM•C:ÅÑ÷Ú«FÁ”÷ˆÖ×å9ð ¼áævšÀè©L{yŠÖ¾ môPlScØ¥ÝPû`ødHºð‡°ŽÏ²fÎØ¡x¨_·º§â9Éo†~B}on%¼šHéj,¢dÊW½U¬?C7M‚Ú›ï:»c»€(C_KÃWU˨Z5ô Š_~”ÛG‹PwY…uóQ˜…V!Ðôˆô§+„¼øM‚îjþø´Ž‚B€áÖ·=b \ì¨BobŒsÙ=ö©Hv*ÙÍGìiZØ@Z¶vY¡ìµ·Ù1?DfOuµ‰[:’nà+é ŸÐ£’Óâ/ÆâIŠ¿Ð{—Þ¨hÈ;rÀ›’¡[Eß•»UñsÛ*£O¨È n/‘» q/†>…åìß6Ä‚˜w,¨ ÏÉe Jö†ßЃí6Öšb ÔËb®Û77E…Á{kw“ˆìôW™î ©o\5,ÃEè¬ã——óŸf3¯ üU3`h‡p„(P;#â?öMêugk®ç“(¬Û/bõž2%˜ÅvØÄ®‚Ú§ÄÅ¢‘ìa÷Ey.j®ÑwfŽ•Ñ ù ·!â÷±~Žfk6¼yÇåEo+ª¾ÐÌÛ¬ìüB°•­[¡³^†n5Ñà­ýF™xhW”[8±pŠc·½ó(ìt5Ç9!Uþ˜½ ý]þZ*u¿õH;úR}U)Jí”"ÙjnbÇöf§[ÏGó–ñáß×b "Á*—´ n¡ƒ2’ýf;¢%qJ ©«Ý4Â\oÑq”¯P +c7G§ë}Cè-d0ôÀo¼½îÄ¥_¡ä˜¡W©ŽB …¬'§êb_B¾Ã<“TþõUžB ¤YcMB‘?ZqªrF Áx?:ú¬ÏÄd¦ÅÑü’§`~ê÷#ôÜL·ýùµÞ"ô× ô7¿ÀçFÁ‰Å|Ù‹y,gúØÁ¨ÛKózMØ÷œéryk;Õ°pq~ŒÀ”êƒÜÖ×ÊeRÏsôõj’ ñÊ0ï˜nJºå®¯R Ú(§ªÉPj=NXw¯û8ˆ·¤–O’“tW¤ÇKžÈ˜S)Ÿà!à>¨ÆóÁ*mÅ%Ù¦ñ‘oÌð¿¤ï¸.ž¸ÝlŒƒVà(Ó®z+t[ÖrÈ\n9%[ß$õþ”y8œ!¼›§…Mn/ÈOŽšWЬÖÉüLýE†žƒ£–­±‘@ì:¥Öw)!´Bô£ÿOœïŽ]d¹+í§ÍLm@fR çÀ)2Ó£xÈ‹¤š×1HÈ,*jÀ4gïá–²+ å|ƒ±÷Teoí$]·Œ)ú•ÙUÞ™8`ïæS)‹Å&ŸwÆ-¯LCko>mJÚIæÀˆ€¸§tuÂJ ¾Ðž|ìÎ…Á•àØ üÝ‚cÕi5ò|½TxΑT#ÿt³-äEi{ÕOÝú>¥ÓKµ¨]§­—k¨I¼>½…º#ËUHöëö%ÛŠ›õÒP‹ZP{¶»Žß½õ,g_ ˆ©Zލäu7š£F4“7[Ô»¤r²V$O¹™q.ç0º“ƒ×­(™LnÞÒŒÖt^õþ×ïÀ“Ãû!“d¦þv~pÙYþ*æÙœ1,T?PÓõŸÓ¼-ÇtèÊ _\4/€ïü¯f×+vÓ¿–}PÿHüél«vd 1ycÞJ‰ÀRoøþÚèSæ²ÝDS“d¨z¬@(¯‚Òw½"ò“qÃju‰©)ÊÏCÕQÔ“ð>÷2˜šôÍ…ßKU[;Çàn Ï4ž,ð…ÍáîN¡< FÈn¿½lÅìx…¢ÃßǘË,9Jq?Sm§K2„ìóÒ}ÍÔÈcùì¬`›49%“RjÉ¢Ža0VûI††s‘%§&¡ŸŠ¬ZxäÐ QeÌw½¿;JYþfœš‰ ôÐ÷þûëhܘ Zo1‘Ù¾ n v—Io[fÛ=â§‹ôe>UE·cØ:>éT˜F´R¯²ópú ©—Ãh¸w+C? ß^ÀËü"áÜ™Ÿ…á®…¤ ¾ÛHqàf2fè”3%‡_CX*Q)Ë•¼ 9¾O!È«Ÿ–@¾CÈêBÛ²¦ÈrH› –P`—ħÂfæyÊ)`ñ6iÓÍNYÌG8Z“k7Î,Cv¢?ç ^1÷»‰’;'º¼,À#~™¾¨µí¤äÄö„ æaqq>ÙFîµ;ìÏ7­HxG°‚D¦Uÿ` #Í^'ÿF%:4«Ã_©€+'"ñ¤”¶ :uZõróíØ‰¥¢!„„ö}CÐC1zsW‹Èj_G¯ímÇ–ŽÊ×êõ3a3sRcgOˆ‘ƾï.XQʆ%«y±"ü8#‰buåP†’yÉñïCùÝ»RYvNË—†n÷™Ð…AdÍØ¸4€t–¼éD÷ƪÐ$søÏí/*¨#³¤Ï],†&šŸGré ÖÒOÇA¸vL·Eõ_E9ñÃøoáãŠ| l:°sOn½_Ê¢EŠ)[EÐZ} ~аòÆ ŽÁóyOàà´(7*¡5 O‡B7B°úɱ£=©©;ÉQ?âµ>ÁÀ£ô½gØ;'Ü•óÔM"åv•D– íÉsSÁØ.‡(«ßâyœJÎFC¿k|Ü£!èxÌÞ”ÚfHôíóN+¬—Y¡)[ðT®7ÃÅÝDªnµyjL›Ïþ‘âלC>v½£ÿNØt¾ŽÓ#É—(½BuÀÖðÍ~rv‰GB)ðü¡uhFb÷vÍØ N»h*B¦ûö ÇH-BÔÕý¸(£Q—d‰:çñkužÎšå$ίiìt|¼ÃòÐÍŸ1Tά°‚ü¶6Š( ©¼AŸÃ“ pó ç MOl}£cIeÒ4Rõq¿Ôø‡:óÕè\YÀ^1@;Xh󏨳*ÆèÃ¥³oN~qÇè͈I6²Bšjé-’,'_¨¸ÐB><_x=ËLûõm´Ëaç`l-®7ÕdŠÞÜJø¯%[¸R·tÃ-Ô·:Ë+öß‘µí  ïo s ƒOÃè¥ÒvÓó;nA:¯ïá§²¹ÖÅŒ žß©:çîô!-óŒt÷æ…ªhc·äW—Ú¢ÞÇL4·Í¯•øµxÕŸqt© „ŽŠß”…ðüªá,ûæg´ ðùGÎ>õkk×´¥:ìñð`"TåѬÜßi\IRrØÌˆm«Ñ°ÆEº¯T¸%¤<^#G9Ç ž®×G„„†8Ó±ª8T•8ÿ«Ïµ¼}JŸGÝhx…3§”‰¦×þKœ¯yØà#Jb:„·¯/3VŽ.,Û@5kq«áwGóá&Ä]@íS¡u΋±£¾ep\$Å#Ç+Æ]j9rÀ3#ÂóODc ®ƒÍb$FH‡ÞˆVí_Ì´Ñr6mpõp²Ä5 «ÛÄ…e¸(Án´¹ñnå», ãf® ]$y—zW¯ú9Ÿ2·zÜy,ÇŒÃ'Ow ¯Ç&ó2¢=jMjÇ•ï¦&ÔûÑÙ¦zoJØ…Ý18ÍØØmß«F‹WkŠ'­¿‹×9ѦÇmP#ž~þ…^aÁ»Wìò€¸–6‚ÝЖ¹®W/ƒç\œ“Rì†Þ„κ «ôÖè¢;Ô·eºôŠ%M‚,ùåµGÕ°ŒùU¹ó²²œ¶Nx‡2~º*óÇ«ñ«§/e·v¿)RZ¢«ÅƯ¯L…ª Â’:f»>³*—)%—.æã¸VMì'ÂCƒïÄÍRj‘1Ó­ÁÓÂ[/´LY$|MGñì1¸á•ÅâôÂ*íòîùd죴ÝUU%_¼ÙxM5qÖ‰I|Ò-~,R¦ÿ²À/©p¡4¦r>ïûDƒ¼ÓR͹:J ÷õT î]o:oäÑñÉÒÒÁ§·†ÄÚ«e½¥à¡M„&ñOG³óm·-´¢Ç'ŽòA ü+oÝs¯ù•Ú—óe÷Ajb!_³øKåý0—§¹U¼³¬.¼¯îs½,6ë0õ»<†Š{«J nµ¾û3a =xótûh Ž åðäǺA‹NÈbêsñôγ!ÐÅ~Änãk“ËFÅÍ)LêZY½ENåÂÅb߆•ÐÌW…l¨Ç-¾ª£c’нÛÞ®4 ’Ý3Åß{ã@Âqƒ2·Ý pZlnV} ³]IYÙ<˜ø„{èÝã#j¹8‡ˆ…TˆUq¹Lûy Tx¯ú>´ã1$w f¹çæ0õÍ“Cš€ég•TC׉/8?ü ý%O)²²ž¢îó Ž_>LßE‚r6ࢨi×sØØKûB›.‹¶Ç|óR'Ië!q8n ó7¿´Õ‚poÚWáàPÏvIz–¡âZGãê™cIBÙL{áü¸Ù6–÷z8Ð[d/¬¸Δ´ ?›±@ÈMßGÄ¿>›qA],Ì“±µ 1½ÄNóh5¤ ®ì-“ê¼îÒy> ‘xòö¸ô¶ãů½´)- Ùÿ<@ðçË)j‚ó>0HªþH SX};/+½òt«qx)G™É­õ,~ôð‘ÞüeÞˆc<‹à ÕT¸’Ãÿ!OXÔëµ šà/zâÛ/dF/Ù6=%º¶Ü­ÖÔþøƒEF0óéU€‚æ‹UÕ¶¬¾{¬/|Æ $iÿûæÅÍB,"˜CÄëZœ‚xҀǗ£î:eCÃV¹®Z%µ-U?$QÈ&ž¤ }ᛩ!ËøÇkkø˜â9ƒ——ûÜ$)°é²+´’aò\èÙ‡‰•Ò 0ß6¿‹/ÁÕ¬fibÁý`ƒ"F«Û©ÑB¬øôqí†T/UmÊ®@}b)vS6¢NIVÀµù­Ôa…G,ÓŠ*½Ø¸… !iXÛ‚‰ì€áYs†ˆ¢mŸ©b&R ÃRqâñæç†ýÍWá·ÚW'­‹Sì"jvάDWÔåe\T'vXè)["dp†ïŸ7Ñ;‹_Õ1 RÒ ÛJ„ÔU—Ff×>r%3Yj-캲ÝðGúùÝdô[¸C«[%‘Ÿ xôgnO"Hý8{6sÞÏrêM&êÅ$ ôßlµž^bYï$ÞgI"úµðÅ6¬“¥ÝªÅ\=—"’Ëc\Ô#jßøB‚Àjîߣô´9pqa”¶Ç-´c’OXâÞ²Œí‰ÖÓ¼%ó£ `§C¥ÙTô f}zl+LÎ+Z‹ö~6¡÷KÌù¸/+ªUÅ é\)×#ÇÊÀìAl{ñ3€• *B7ÿí|±ùFŸèÞÍ•5ޛРåòÓõ:Å8µÊpúžŒT5ÏLºnï/A¬¸t„éq‘PEüb&.ŠŒÝµõ :—éÏöt³‹g.>xÿä#8^zõ©{?5ž«ÝSËNŠ«Ÿ_Áå áœô©ìDþ ñäCý fB š€™W½võÏùb÷?ïp{i¡¸x 6`|mgCɵ»éÀWúͱ6½a²QÝļB¼9÷#ÐO-ç~JÉ(1'wrgahôßþ)57µáå¦7±ž0F“ò‹€ÜÓ6/4þÛlÔŽt*ûöΫóJ‡ù‡®²Ö{ç|d¯QEŠnéQ‘|XS•&]Õ•Rïªã«ÜòT£ fÑAçŸù3'8*3¹ö¯!²(y0z '_I1’9åŒ"9ïïˆ+QtÇ.››~UÅ啃• G6Ž:PßSñêžkCšxiãNÊÓœWô²î«”‹Q¦¦h9_Ï…R¾.A¿;ñ¼g§<•®×í¯s|GýäÔeDC¦™ sgFTŸß’¡›mtÝ7¦¡3fFiÊ´CS\}-ñ)´¥ý®¹'gñ‰¹âòѼœÞ@Œå@ÊÝ;¦|Óœº-ë1fƒlg€ ¶“ñ‰ggŸÒ»õTR WWÏ/8éGPÔµÊ4:ÑOZûæóšðèbçX±ZYÇ'žÐ qß’òTÜCÝ|ˆì>LÍMà ¹ 0OŽsž,m” äÊíX%ﺗì…Í qô;éºÔ*žKró¾D³¢Á\›ú4¿éƒVîÆªºÛ9wûR½Á;Så"3EÑñÁƒmÊÎfM jîUÐP†Í—|^{êV!þÍÆ¢;Z¶hvÊ]ŽÉ±(ž>®D¿f3cH¾å>qÎŽI3±ÒõÆ×ËŽKò&4(drœ {ÑuOºf–þ2•9’¯ØoHbñ¡²ؾÖèý/jÍtT|.¢Œ%¤1¾¯hZÅèÔiN p“Ú@z‘9Ëpñþnýdpp¿#§â­íßÒúôMð…x¶|Ã`\¦•Ó%Õω‘&× YIìç¯ÉkÑS|4œ2ÛáMõìïzøô ˆudνcê×ìKüü,§Xï]ïàÍ^Ч×xê:…H®ã¿á´¦ÑŠhg­ü¼epa©’ª¿ÿœq°{NÂWII–vhž§Š»ë”?úƒ’Îm«.…›÷¨¥ÒÂëäšÞŸ¢Sy'½"@ŸAÈBhÔ /,Wµ›Êâ42ëM¿w`™™ˆ±ºÃäz-DÕ¥]ÔðDPW^TëåøÑFÇ7l–¬>SÂøÌ$Oq¹€,Xü·Â.U ojQLfè­l$íß|?±ÑÞ‚oðsÃe~ž¡Îk‘?]“5èÜ6†ªÒ×—‚è g&†Î_o½¼öhrõ7·¼NãgÛ¡û/oIGSs·Ë+¶9†j¥xßhÙx4»¿7U.˜3j"ú²JÛѦúé‡nü‚³‚q臱Q5=Éï4Äv öå‰öùgöorêì£}©4÷ZÂ`¹ób·1©ûµ„¿®#5R†¨…¸#o¼äýx<ßQ!Œ» í¶ð(¹H±Íàï§¼1µs’=’)%×ZvÌ wõÈ]-ÜÉ æÿijQe޳~õlUɆØÛÛÊÚ2_CÙ8i‚è«í&ÉŸ‡cä}&Âè ø X I1crê¯FÒ‡ýÞ Ü êóI5#VÓûÁRÔˆÕWHXZŽÈ{–ªÌVâgÕä cîÒô0Ç+>å£Ö°µÃ޾aˆ.ÖAÚpº+‡<™ÔšUáÈS™äš‘û&OìÂu²$ÌòðUëá~Di—X²SnÁ¤9 »>ž‹ŠµnÔ#,~©ç|°)ôì dhÍäé¢Ü÷5Ò'C %8ÿ(³Þ#rQ ó²G ˆÌÑÄ6bŸžO»JýñÍzå™®¡yš¢ ž¹.ZžF¤“+~•²ÉÝIX–›lÁ µ±YØHr S¦°¥œ¹7s±'é›t­#ÿ}õv/þ}ñ»%™‘ch3áìI?3³”76ì!eMˆwµ°8Õ˜³8²ÆÊ ŒËòÙÚÍ”$DiûêØÀ>êÁ5^·c,»¦YQ2Ù(Õ¢”¡ s¨fñ6¼÷ëAˆÓó>‹T®Úb¢ã¡7áK}zižhý&?59|¥t¥Ö÷q…„`ßÉé~ÜOš‘(å®”ö ÙwS©|x*þà?§dG›Gßs«±n]Írß¡ÂÙí+Rß™Òã«r`šÉtOYðÁ«FäämÒófŸ¡–O(Õ`ïôÒùbç«îMæk£¨ÔÜqõ/Ä‘ü¨‘DœÝK¡³n©ñL¤ý#*ÖNpŽ9u'+žÈq þ.ǯÐGèìe…nnu¨ïxoj2"¡EWÌQ"[ñŒHŽá.7š¥1B¶‡EÁW~Åþâ˜ÕË‹hmŸ Ä ÄL¨þ£Nhcï ³ýg%Å“#^ó”ë¿ Õò‘ ¥÷ðË^kR‹³Có1|dXËi.(‡?ì~„¤!ÄÑ×ÞWfq[ÞbgPÔX?ž § vx’z’p—ersŠUôÇÔ¢–Œ;¸œ'ùª=e¡BpïÞ5E² p¢ »ë™áÏkFîé’£³µzýð_óXh'•‘Ѫ`@ðùíí3ȦÓŽú”&PófH,êÕS¬³·Pþ´ÇQ9RBsgê1q{'p®6·t½Ÿ>Zæ›þ}³µƒk2ËÿŽ¥]MÑä‘}XO–úxÝËiÿ­büQ¶2ôbC=¯^_Ï@…§!³î»ƒ·Ž †è-„€öä »†ž©y÷˜L}µgCÅPYGÐ]ÿ›9þÒMW Z9-w62%]õBµgüÅžê§ËÑg®‡O¶¢^Ðúl&ñµ:4þ÷TZþHLÑÙ?ïíb?›Áìe‹Olåt*»»*—"kãòÞÊö ŸÃ/ô \ªnc¼^­YüÝXRÊÍÜ[›ƒwÉ·Ô5ƒZå¤ÊI°¾l•¨/·Å´¥½E´÷O¼.Šö²©‰ó̓’ð¤€ö³ •?•–úžñb:½ü«‹[1W$§Ÿ ]Wìjèk¾ÖÍb’¾rQ,.¬¼ŽÏ|·á"•r¹䦱ðÍoµ¶r\‰¦¼ó8÷’î´åÔOteœÔïQ/@>pç[ŸÍ <+Ø,zB²ñf¥®HUy[ì?×x ŠÇ¨W@¾5€Êc‡>†jxf&ºûEU„ȱ¡È¡/Õ¥i `=ËáquÂ‹Ô Ïu$ùªŽçÿšVzþú%òõÍeõ4Oh™+ÙÜN˜—žã×—pªK²nèÄÔãç9«ñ¥ó^x9I„)‰S`ȼ\ÿá'Œ¿‚@b`™Ó'™ÿ$™^>| Y¥vãÝ“®¶%‚ò»uú)}G¡Á–;‘žÈÁc¢'D"F?©¥€}„Å`æ•øî XÎ×\o.“ ã,i´{åNÖP}÷cÕNƶÜH’Ò©_[ëâÕ‘vb+_å£ ¦Ãz€UhåW g_Àg}ÚHœÕ{ºb]7è:nãöÂqlu_Sìõ…€ñô5½‡Ì#OIÑÀ²àHãšéÓè!bþ“éã£fØ oö™£‹A •‡¨èσÙ#EŸ0^í£oükàö ú«ÍÐ&ÝX†äõ¼_E÷µé;$¹‹{CÚ,Cïá+kw:|ük<§uÏ3r0`GÄ%ÎÏ/aB…á{„¯¦ÖI®B×öÇûÂ6ž´ö}S±ßúâ…slM€¼¿¥A`±‰Ÿ¥ý’ަ÷ØeÈ'¿B{Ýζ¦=™$^þ^ì5!ôòÚÂtþ^H–¹îÒßHÞe\nÖô}5eª*pi€üÝ· ßÊ–ù¶´YO âÏgâ„Å¢ƒ’T>èÕ2jÌ\V;a¢#¬×Šôp éósxübzã„ŹÄþS$´Áe×Ñ…þ‰Ä¨•ócì¡%5Ú(&ûù µP=@é{EÀ“ªµ^ãúXž'!KÁ/Œ;b%Ýû2²Â¢~3^X!ùØŠH¨7\C’ûHÚÒâ)cÜøÇ¥‘´½iK8£¤xYx³pƒN*Ò#7VšG2Ò¨k]AhE2Öš÷PXâRç½máÚR?ЦY ¾£ŸÏt44Ê%%Ò¡Ãÿ`L10ªÉï7hètØg­¢dAÑBòöëŒ7… ¼ÑNCTI)ó—Cº¶^ÊI‘D k1FË)üLݪ‰Ë)wO"¿ÑîYõB7ÇÞtû’`M9¦Tm.ظŠkäàCå&„%Hg é"ÕÆ'KÆP ½V¥}Ì ×}:V·7ZÄ´4®HŠÝŽE‘Òý塹#¤°ÖLIH ¥h–æ£R^õŽu?—“Ý’6úù>üCéuÀƒEÿ²Å~Ð!yâ÷%1}šgQÎ)ü¢"†<$ÃÀ—ËÙéHO®^U NÞýÕ#ÓÅ€ÕŸ„Ãb¬zäOb¿Ý‹i\gñRw×ã ³I’~‚/nfr±F"ÔC¾ÐË¡¿@Ý)s(­ÃB6•$ÀúºÊ«ÐY DŸeQ  Á³¿À1ÔUû¦H¶¦‡3M ÀEz„³[9§ÇE,ñ^ÉXõGêÊòú%>Ø}r]‹áÆÂ?ªG ’lªw[[LßUq?~|gen/Ïl©Á‰FÕhPwó2þEs˜Á1ÏŠäÐëyfðŒ]lwWŒtˆû´PuöåWIÙÍþ/daZ <[»F.ýÀ9&eÉZ‘žW£í°ü®ŸÜŒ‘Xûa¹hCNÎÓÇòk_K}57<^Q³£c®5÷ú™¥PQ)ïÕÒêúµc õYOG±;›Ç˜.3èF^#â¹ð32(9n}àù`¬D \eàN¡úi¾ï&^QN]¬uüXx-“'I9Ò÷Isfª_õú|/¦Q 7kYŒ{¢Äõv%‹hƒ®í$ÏËf«|̨Êf ¶?:°;CÔç,cŸ“ űs~–ÆX€¬ÇjƒœÕiŸÉ¼½ÝcÈŽ™`xß(z¹\.Ùo÷CðÛÞ¾û¥ƒÃF“Y >ÝÔ„Mna¦1ëU™ @yJç÷ÇŸ/“­Õ7Z{ÎýM=É>®@ ¡¼ËÖƒÒ\ÍÒc8¬…̉¨á‡`VãÅ›Õl¿<4‚vŽ ¿Ø%ö³El£3“^BSb¨ŠøÀGèÜ¿ÃUK8Q&å5ÈäzfcV¥MÐÇ1èˆÆùAß[—•ù$:ŸeöÇ(þº êó–ÿ‰XyGƒ9Ãæ©œþ>ŸwXÜ$"1&ŒèѽI,)wüEúÍ=¶g'ªq_ã!g^Ø:ˆ³Eå£b¬EìH+¹‰öQÊ¥¶Â÷îqÙ}Ľµ‰~6ß™Qv¼V²Ê?Zb‹B!Ûô·÷pp&‘íK˜¸kÓt„(;VµÏ=ÖC]aa˜mÈÙ‹F½—RX¤¦ª¡)åëaªÞ·k& -Œe•j;ßhö>TõÊÛqbÉ€†½3´3‰ëš.ìvœ Ý´5ÄcŒ4†âS™"ä~·ü×'ªÐÊ“8ªdçUQõ›1X‰üÂKŸÕý–Wa!¬ñ¸S-¨⊟ô)œè+‚ÔXXBuV–‡ºМÎBO4+>´Ý~¼ÈîvØŒÁýŽýŽhG¢¤¿dò¨·ÉÖ†lÎ¥9<ÚèÝ”ðþyƒ¿sáÕ1råR‰·ì¼+Y¼á«‰KÐ[¦7¬¢çü-\ÉC_ÄÍ8¿ ’·NÒ÷üd“Î,4+f°{Q©à®­o¢W&_…hêï‚(WÞ½ô8á¿?c•¬ˆ #­.Í&¥Ð:³O“dFm%Õ[N9…-ÌÒþ¤»ïo%±š9Š»(Ë+ÇF5èp$Ó¹oTQ7ÃFqiÿ–>nõœÜÏÿÂÅâämDgÙyg+òèy´J Y »Ô%) Ì‹oì0’’çW>?ÐÑs "xbïdI‹‡ Ó<_Ï÷‡£I*CÈ\>i•ª8Si•\ᥪ†ýš<5|GMM¡žZ¸:B _«-_·І!ïÛeWî(ÓŠªq±ºbÇø‰!ž Š$ÂkäTÓ:àÛm6¼ÇI“ooºQÞ¿ío42!¥'P­Ü-ñjÿ¥Èþ-J=aëJm*T'©‚ò6ù¤LÄ Ûœ©I¬ÇŠÛÞê¹Jœ ™‰ÉÂo_:‚u b ŠÀç—pýˆcüíÉz¾ÔéÍ¥ÖÊ 3ûá)7Ý1ÿŽ­‚¸/ìb$ÒkkÓ'3~K”ªiÝ Ã~–ºÁÜx›‡Oz pl\¢DvÍšlåkx ?§é‰ËáUgp‹ ßäSFs0g¨fS®hˆÕmãÏ9Jõ¹zâ ËíÍ+o1ˉC2³ª/Ðé—¼9qÏŒ‘¹Œ—W`>Á*‘éÖ(‹v¤CðöõÆ‘ÿ€“ÀÕ¬ ² Y8rÿVœ\]Ò9ÿvŸª…ôf ™òöÇÞKcߌQiÈ£ç=çáN„¢^2áFŠ}©M%×Éô=û_Ö(ó˜5QSÚhÛ³ º¾ú©· ÿõr›’HŠŠeññÀÑßy[±på´q×@ɘ#èŸ'Ò­€Ùº“³ÍØ‘úI^Ñ—_‘†2ú€,1ÜÙr§ˆ}ﺈé{Ñ£0 éÛB^.8~°™Ïä‚l,â[ó9“Œ&{Ô­üZGFky 4üã5 ѧE'Õ¨@BRJâM®¬‰[ÅXØû~@ºø`7H¼àÙ)Pc,št[™|Î=ÖÛ2LÒÚí,vúV{7Öc«[ôø7Ê…ÔçôqôÚÃѼbœýúÈ“Óv—ô–VrjKÑmd=Õ¥µÌMÒê21´Q#÷¹ûj{ÕLwj¢áÙÍVÄI¦*9D ›õe̲¿£H‹M½¢3è2Ÿ”ùÚŸ FrQïÓ·‰©d\&*‹‡ÖrËÊ!+ÿ—!ŽÉjÜHÝØþ¦ ÇeÊo²NBœð²¿ëÙÇ89ˆ`õ%× ˆ…Œ·Å¿Y,ýDC¹eFÑ2#/~DVȓǛüâ/õØ„_Ti?fH°&¬ÃŠ™Æss܃ìôtP.!fLJ\ìYsùZ,¥fY’t.7‡£2 h]CÛ+Èûïm/r\LˆlÒ?±Pµx_kú‹ÔÅ/«N°Ãòc$½óʉK`Éàí¢¿µð O¥¼ Ë‘ 2°ÌS '8ŠH%f­¹º‚<¥‰•mzy‘ôàh[e#µú¾ã•$õ—Ýr}&³²rËoÇdža:Ç4åo?xÌXYFw¶%?ùçv¥úöF¿ýžqü?ø-A8òn˜I¼ÊKáF2ùvdÒA~–3396®æÍÂ蛾ÌÊ¢˜I;Òb ÀtÇùøžæ³¯•h%@^ Þãý‰öðUh$ç Yy–žè­YXÚ`™ê­í|•â2ã)l/õæ?͘ÃïÎÈûÐJ‚¿max¤IùëÆâ Ì}䑨?ﺂ¯áí=åõÁˆcFìx[¦pÓ0ÛŸ¦t×ÿ3 ‘4íë?Á~«ŒíM§i&a}˜éR„±¼>ã¥ùŸ×6àÕqÔD×?R…ì\¼MïjŒŠYþ¹í Ì.„ç¿Ñ£a.xöM;(®Š7>–¨"-DX0;âé(<êPœüvÒ_ŽàK]Òìû…äRªônuô!ïr+æ~¼W¸{C‘üÚõÏ[ÿ•_j¸ì¤:©ÅëN¼„f#»7滈ß# ¹!‘+»@ó"ÃD^?òvxc½t.á /G?Æî’9»ÆäõG–x)Œj»üä­]c´L4pWž—5gô|ó«°•6!§°©kI†ß§x¼ª36>ýiÂI¬=Yõ qR‚E7Ÿ÷#e8ϊˉ&ÝY´ú «~|_òt4ã ۘÞ#ÁZ˘~³#ð4=¶ž¦„Ó½e%–NÌveƒt-,ÈŸ%FO]—RNoö‡¬àÍ64¸åÚ¼»|a&z=ëÔ>yMíOâ²M'3Ò̦7mS4 œ1¯º€Ÿ]À¯ðbÍ“ØhíEĦ8ǯ«µðoþkòA¾©òž¬†NYÞÏigµÇ´(vl‚Dd2Z]'þêAHnøzà̺Ô;ïxÇèÞÛ†y`Ù[`Êm•ø\ó:Z©´ÊÅ '2„jaÂ`ÞK s1« ÆÒ”¤è׎lË®ø"d/×&¬¡XßÑìgð¾Ú&ÀŸŸÅ¿#„3Àú à´ôn¿n‹7 §‰F-BZ ÷ J»l–kac¾F{¡Þ)Å}@¡‡¨ÏCA†ƒ(ÅËrK£fÁ†µhŽ?¥ìaü­Ž*ÅF©¯ä 0y_Z_á5‹,eZj\å êIIËŒïoŠ}‘¹rrú¼¿]â2¶e’úDà>Õ9”t]ÔSÛ ÊTýœXAýŽèƒèÅsgãž<œÑn¶ êêc ·Ü>3>1xR³Ÿ3 !¶ÓŒ‘>›P[*ùŒöýKaÑóéÔ è§!cíNB=f2±>ö®QçX#giä¡Jr$]§êfeóŸ –¾ Ã.¬È ̰'KF#õÒtÎàÍ?]]/×o[”L¢¬]\¬nf×€ÒrÔɵOlõüéCK©4ÎcŠ˜‘öCè&2ñ¼lFW>Ü·CþÝÄÚ}‹– *ÇÖö2ÖDÉc`: €3Nê´øR ÉÌÜ’ †´ÒXxQôÞÛÀÛV}Î}c,ÉV!úc´jÒ isKJn¥¦#dË]ÍR 7ÖB˽z÷“«¡å§0xk:ì.Þ¿È…hô%ò”ñ&drßßçµ}[²éaöC+ѺXup!K¯M ÍWfÚ`ÚÍÑÆ%1T„ÉÕë +f£Í" ŸÂK <ýLÉŽkqI-]­i°áxÜxé?ò¹.k¹1ñ^Z0'þÛéÏh ˜6cöÖ>¡£ >.• ç Ѹ»?‰M¦AÚ1“¡XB¤Fí ”ï†Ì3Œx1onx§3k×±BÃpiqɃu|Ó™O.`Óª`‰Ñh/…ìxÊŠÊ ÝPk>çÖ 1‹ßÍ2HÀ:²²5ºMé†|¨ÆJÁ89œD@Óõá3š/ä4maQ¾WJ*úí¹,A¤^ð<Õi®[¢?:ÅËo”/ÉË{«Ö0 •43äã&è<ÂPŒ!LÒ†ƒm¼øI6±vœH梫‘ãuÐK¾¶žÊ-R­ç÷ˆ po!j!‹?¸ †fx9ÈxFœ½­ùJI?Z*@àÁ©7Þû qó¡ï!Õ'¦/Ɔ†¸#¿Vój…Zb]Vƒà“ââ›É‘ßRåþVkf¼=‘ê Y< µ¯‹ ¬¿W´î^³<ª¼Ï­<ÀÞżIé8‰mµn¥{ZªÙbÛÝÎ:›bPØÇÒ¬«v}Ë;C~¢›íO”èw-Õ¿¼Ë"MÇ¥iÉp@U+Ì%gã°þ±¤ŠaÌ+ò½ñÖÛ ÙϺù¼c}>³÷˽)÷^ÄS endstream endobj 86 0 obj << /Length1 1545 /Length2 8074 /Length3 0 /Length 9092 /Filter /FlateDecode >> stream xÚvPÚ²-®Á lp‡Á‚»w  2ƒ»»‚»“àÁÝI 8ÁÝ!‚»É9÷Èý¿ê½š*fV÷êÞݽWï‚–RUƒUÜj’B\X9Ø€I%u^ÈÅr¢ÑÒj‚]ì@šÑhµANÎ`(DàI'©Ë“MÊÔ剧…ä]í\Ž—¼@ €äÿê$2u[”ØòPÈVêàé¶²vy:æ?? æŒ~~^–ßáq{ØÜP2u±Ù?hnjЀšƒA.žÿJÁ díââ ÀÎîîîÎfjïÌu²ad¸ƒ]¬ê g“Èð«a€²©=èÎØÐhšÖ`ç?ìPKwS'àÉ`6AœŸ"\! 'ÀÓá 9E€ŠòYñ àÏÙ8Ø8þJ÷gô¯D`Èï`Sss¨½ƒ)Ä ±X‚í@E6€)ÄâÑÔÎúoêf ¶35{"ü®Ü #®0}jðÏöœÍÀ.ÎlÎ`»_-²ÿJó4eiˆ…$ÔÞqqFûUŸØ dþ4vOö?nÖu‡xÿ ,Á Ë_MX¸:°kAÀŽ® 9©?)O&´¿mV äåç€ skö_é5=@¿¿ÌOøz;@–OM€|Á– §/4ogS7ÀÅÉäëýOÇ¿Àlî0Y!hg2ƒ,ÿÀO—ïö¼>iüõùë—ᓼ, ;Ï¿é¿ï—]WNE\B‹ùŽÿòIH@=Þ¬\\VN €Ÿ›ÀËÍðýwUSðŸUÿ•ƒXBüû4¥ÿìöçý3ü¹Œ€çR†>‰`ø[ã@ ùÓŽÿ³Ò‡üÿþ+Ëÿ¦ñÿ.HÆÕÎî·›á·ÿÿq›Úƒí<ÿ$E‚þŸBÁCŽ'2äð‰ ý >©ýéAü?äð¤è?ÒspØþŸÒ;ÿòØ]ÃMÃÜÕÉéé=ø­×§Qýÿ~|@ 9ÚÂ,Ô\0Ħ6¤ýºZœÄugLxŠvG'‘Õ{Á©Ãõ9™±*+hÍéRLÕ¼k÷O²u}eK#a³;j_«^* ß—M²¾ÑŠ1,ž¦Í7Ëž!¢Bra%CaÂ=öÀš¾¸œÂͤgFóÝÃõÎ[3öfÆk¥B“Ó¹›˜†XŸˆ þwd‚Î[â{Š<áœwÉûhìf¶a΂ùlÃýH´yyJ£€Þ6c =ÈRû—ëQt °Žá¯W¾H(Ç^2í’õ(Ñ_uBõd=z„[íÕH¡Iƒ8læpØú—]>×3®òÅ`³Œ`çjKTìs§T|4mýœ²·¾,®óE=ÇVÒ}‘Nù$ôpô0w×T§D“e ò°—TÓy;±V2{¾¦Š˜D£œ¶·ã¾Ä´ºŽ™•ÑTÚ¼×~W¢ô nƒz{nÂS_¶#Éü$†R³Zw#õÊ×ÊÖ‘?û.á>Aü…w廸wĵÈu˜zèÁ ~J/Ý–ÎÌîwà÷K&MëÉö5îð29÷Œ¡¡)¾Ùc=.mÂïnŸ'><È‘³Ý‡ÞC¿¬DhÕ*É|ld¹_ÛýܪÓ|¢Y7CaöÅd•mHÓ‰äå-ƒÅ-©œ:?Œ˜cÙì}áO–Òn˜Ä«€zæ\+Ó±EõCªD¡c{Ù€lFÒ©:¬½Æâ0Èx}UÒ`26i«ýÓÉúÃo™C‘ªÎßáí­jªÚ³ú=¤5âғλ} h¬ÞŠY¶(Cæ137MßZXôz³8¡Õ0´íF=c4r›¾5yZØñ àÚ¯¿Z}#ïPݧƒ:G7ûžF {•RTÂ¯ÌØÅô£?¼KŒ÷Ž’¸ŠºÁv[`ÄàÇÇý|ë'ÖŒmŽn8j(ÿbh8¶£^•-ïdÞ|/º–Ÿ_Èx˹ç Í[ˆÝ}]𯼧JÓ©’é0 “«?ï#¹y‰3=æìN9žôŠW…‰_ih’ ®&ßM/æâC߆£eq ÄÐ×b".Rb±îøg$—+iï•`RŒ‹+©¸rˆ†ïóíPÿÒ"£"Ø6\o¾TSÚñ c…jã.qSÄB)Á,Ã-£7Ÿ"El bµê|„Ï‹ò¡ÆqŸW\½¼Ž(‘ç;ˆ17srý;‚Fößš’áp¾T½—jâÊ<óqyŠøb’ô‹‹!¾m–XN¯%—ƒ’Ô! æ¸4ÅëGÛ ¬²Vý1û=ÉWb$2*"èègšô†5M‡“À”áÅÅ~õY¼g›Æs=Ññ3²â—‡˜Xñ…ïÛ’KÜ‹uô4{Wûƒ·](O}¦Ç¬˜‘™X&æù±t­=yÊý͹hßáXg¬òÚ°¨xL…7],§iºF4/v*|TSKö¥?Ó•ÓzçàGX‚0›ÜSúÐ?Ù m»tX'QÚ tKºƒ”-÷Ïì넇[´;Ô#²NÇT,nb¹z†|άðN `!)‘«&;¬ê•±|v¥NÆ3»øªâ»ÏÛ( òÕ.ÕÇÏ;LýÁ:Y@…a©0ÍôrôºÅÙ/ÃgËš3ÁG©Û¶×H¼s§Yóßÿì†ÿÙ b™)ÁX¯5!i)ÍÇV‡!§ô^Ýü,;ýþ04é;jžDÍUÔh¨ž:±µuÛ ænצ‚ñZøE—Òùå‚–TÔjzùL4ÓèSßÂqϤª‡}gNµùîóh¾qvÝ!Mâç¼ê!ì®øÏܯu9¯üt†´£k­ÁFWÖRàÝÓúž.P…¦`Éëï…ä3[âr ïðÔ8NªïVƒÌÚ´/à‡§ÁêG ý?ý ‡G¶ácø©éI Š›Js0ÑÆv+âåyxÊ«‘¬¼àyßZɾªŒ—dŒ]˜º[¬ecÍ%´NŒ2JŒÉ×&%¿º o6_ç/;íA¨B×v:ا׿%¼ŽÓ?'¾‹á‰ÜL ZÒ6’±_Ž.< ¡¼½½FŠ)ΰa»<ºÛ‘zÏ,!ZáÓ˜à2?m{\á«®ßA±¥ê½¶’™Ík3ÇÇs÷ê`m~L6 ‡/dŠ_‡Ñ&‚QïÚäºË»Ð§ÿáŠðFm§o7ìQH©.ËÍl$½£‡¿¶Ù51ÒYSïÞZ®pÝŸÜ>ÔÐb¥WèÃ3n|\¼Ê/eqÑÂ? [.s\[tDŽաgÓ&ÅÈßV³?hß̼xgBƒÇ.âÕhÆ»ó@oóMމ%’¼ýÎ}7±ÕÛɶ85ÂYÄ(¦SYH¯¬U¾J+8u¶˜Ê –f,cbTM]x]h%lWÏ4«±svóÙ½=K/ ÁNMgÚ“éÄÈ„áßqd*Âû™œ(Êßt@ý$m¬VüÒ[³&ß®Û: Ę́ž›(÷¿]¨G¨ÄaÞç/Ä|xæ'Þï ÃÞ7®”Ú H'24b#PéPÛœ£A“´ç…(fÌ·÷‹ntÉ:8Ø…®;<w°t%3r›•Ãu·¨ºEJÓVòáÙeÀ#ÈJî<ÆzAŽEI7æPÂÕ®P³Võ‰¶q“¼Ôrª1_C¢·8 !QEÝô œž¹GøÇstÑŸ ‹œ;.í6ˆ§jųõ'´cGò5’ÓWNå|»ã"5^wVÞZ+d¬}O,áfPüDv˜´[Š—ËV\AEÈ ÌµKµÑh¬Éݱx õ(óú\ÒNóøµÒœô6t6pÀiE«Æj‹ ÑØÚN1 ºQú¾^áÍœÊ'õ¯Ú0h©wJ>sçšÐÌÛÐÚà”ÅC˜òûF¡âx¡œ¼P¹lŠ~-ˆ9‘a÷"+÷ÝKcN%aB:Ÿ/sô¬m£ e‡"0Yê5P>Ôc0¥"óvSB«PMNç µ=´y`ïy„ºðG¹/O4ýGbæõ#ÛL’ ‚ cêWß4þe~ëR~µ4Üœ§7ü BÑ ½q^FdÍÞ5“‚ÒQ.-·û!¬Æ—bLqÕ½ h»ô/AþdÎ|v€pßG²ãÍ\’Xíîö#ÿèT)1‘Û’V¸ª nÐÁ2aêÍOtO¶8ìiËÚ…3/š×9ŠÑàƒ h7Èsuâ"p½h34bT±L}*qÀò Å’Ħ Þål5ÛõòÝ0Ý\”»ÖK=OÑìõ’á…N¥²{|b7Ö­E£*9лIVdøÀ¦TQÑzígoìÊe_SeJ Òtûç— •¹ î34¨M¾ÃEK˜äi [Õ,?ë¶¿i>Ï0‘ ç—kC@™*¸zÍ.eƒ«"JC™ Åk¨êFpôfù¹’cWˆîYC õÅ-¢•’¦­»À’s2zçù¢¾™§ %ÆSî³Î2–zó¬þiìè«`ãË™ÙÎMÎd‘‘‡àãEÜ—uÙ™Û%p8Þ#AÀЋ¶lCº:â”$í¿Š±Én=‹ebåWIM¨nin" ã•Zø´ù¸Ì¤I=;½¯ûº†ù¢¥Þ²î@´8dsÑO¢ÆJe–”Ew?Ò›‹’Ã7¾žqø1w×õ²Õh[1ÉP?oú‰nEŠ·¶§ÙVjÕ‹é7R |Æ'a·r¶&ÄV9´5594,W¤O›dÆ“/Tî #L(lm4Kàž%TBø•>M}Í8|g:ûé¥Ñ¾Áè»nu‰'ÿ uìÄwûH$’Ú iqmqždàc.kŒ?½Äòj,4[ÿMŠ+õ,¯ó½‹ÂÇBføÔ›~F™FDò»”±…(lêdÚ´Á>wÛQ²oµXÏK×p“ŠÃ“Ì>T6"ãˆ×‹|šIES^œá7Àß&©Ñ¦Ô]Ózñ?dó;"¢ü+üTü ¡²*ZÜ6•íu|ƒR¤;ªàž¦r®MTÕÆÔå|ÞÔ+8N«ò²¾JõZž;Ç”­Ÿ.bŽBDg¦ç¦7༡“ä›?QZ–íÃéPçÓB¿¸î~À t0Íé1wÓ `Aõ³‰¯æQ¼û,ô>b…lØðDË'ý\D¢2û@C:Ø}-Hx ‘ÆæqUëèù3`[ ñc¾Ý$“|C2L]ÍF´‘¶+»ûØG}ð%Áƒ²0Ã(¬{–7L ÇÔ¹é{½÷Á®ªà ?žÝdÅ·4>=7\w›)žÂkçqù3÷nú‰Ò*ðH­‘ƒV°rD?°,c~œéNpn~`wäo´­_¯Ý‘0X¸×0‰ª™‡•K5˜ÒŸmö<ÓÀˆ ž+g•L IŠ6´¬+û= d&‹n°êWŠßø~áӎΫé:di¦Sea¾UüØU|°µ¡ÚÌ–44}Uµ"+™÷‰À®0‰W­…Ũ¤~©:LNˆƒÍ0×ðv‹ï|H¹Âûl³;XMñlÑbNª#Za Š¸œà±‡¯…ŒØÀ­U‚y– “½Ç8ñѧj@@Ý“ƒ=c¡>Ÿ‰RT_g_Žf϶Òpr;‹îð13ÎcmÓ£\ã½;Ö˜ÍAÉ?Ë ¶uC4铈gS½¡þ5^‡e»±ôÖ¨m°¸R/jÍ|`½š-Nè3~ÅÔÁû¯â±¹Mb×òn,€{©îºIã–X /öþm÷¾Té7eQøz˜v²0ý{×é©~›Öo¨¢¿%ÔviP~=£¥%xQ¦ú’u«¥0ŠØíÛúPw2E§•«2ÄÚ;„}‘g&W`r”/I5 P°u+’‚K²5ªqyVÆC_B0vœè­§ÈÎÐÎàZ†¤MÙVž X™œÛ8—ŽYo“Ð*ª¨¹¼E!V×C¿L[‚4Ô#f­»’Z!©r¨')QÒúmRÿè‹FÛS9>*”(ý¨ÿ¢56Ãèóy÷kt“50¹Äbü%ôh‹7*˜\“¼¤?a-ŽÆq@úYÿ$ÒK£™ éý1QL-_'dØ>?ºµ‰iðñÇÖ.5šý*1ùŲu<¢Ù}z—­Æ[æ¶—Ì#»pJ›‘©“Wc‘ f ùÃ˼ò—ñ¤ÓÉ£OkÝƽIý̤uÂWê Èö„í¹ëصg Qs Ê ³ÁS¾¹I6™°89燯"®5XEx+Ȱάª$ÁвÛZv‘‹'¬„‘2lœ˜­]*¤xÀGÁ7â4þŒ9Äãªê ‚Öêeà›³W òz»þTfhv¦E‡±—»QH4 ŽøûJß«1ÿ0%â­RsFàvsnŸÔóþȵsâü ¿çëUé§BàÑÁ)“zG5wˇ”™²¥æ›2jù7bôð¾_z…%È)MîO ;-UØ¡öïÝ"ϰl"ëk!_@?rÞMÙ/V6Âs…LEJfVazîD‹RôkPcN4¡hè Äú÷Š^ÙŒk¿é#Ïg¨=½-°“ §`îÕ¶¸eåÍhNêÉÔËþ Ç.qi"X‘Ùtmb¿Qâ&Lbê¾}ù¹X½\#¨ zñ¶5O‚F÷ ú­ß."5š’žFˆøáU´ ÛõJ ‡¹hu&!eÔ²„0RÍùÏþÍC‡¹p!DY>Èm½”cÒæÒ½R!^Ù´Ú¾¼öXÆ#ÍÌ©†gm,O¿€Võh.Š;è9©†0M™vIâeµ¬—S‘£9Ù“CßÈ‚<òï_u¾`A¬ì%Šb,jdØÍ}­¦(WÒ%n_Ï^gzÇ9-•à`òe:êvË[b4Qu9ááÓ:^•8#«Ñãàÿˆ•;sëæåãc_¾Z{s;nmq.¶ZvÉu©šFהġ‹ÈK-ˆ +æ‰ßkôNߊoGҰשûš`ÈCýà$í¶°A}Ë@ºh}’ŸõI³ÛN[^·±•?½ƒL>Ò/õ–["âÄq ”9ÍÓ¶Ð’x`‘)èÀ/§Ê‘Ríù‘‹#_j[·ë ú…üŠçènU€%}2ˆ­ôðlú±lJ<*Rxoƒ9;h&§ûÏS±gôö‹Æaݺµßµ0‘ú|©5Í›‘\€m§4½n¸ðê-M‹]¿£TõVzŽ$2>(s£ý¥ÑËÑÂ7RD7RM E„©˜@‘õZ­Pµj8™ä䃣/¯yán­­`7Óîk50¼ Û’6FqMøÅÏ)ÅHÊ©ÙÆBöQLw[ ²Ì)‹a»òes´©|ñÙiäg÷ JTðòxŽD§öI:ÕiYbÔóñ?õC½TñÅËPÂrwú ëü½"Í` GQgLø]ªGïÚ½CVýLÇ>ßÿV&S"T˜~µa½F“vú&c z÷ýSuÅ+º]©ù(ôõ“eŠM¶¸GÉî4¸åKý0T‘d#ÔóõO9 é¸BÈ äŠÅ«àÒ÷›Êsd½JŸDt¢Õìݰۋ§tn©ƒƒ d!£™¸Ã6êöGÓ¤Ötƒ_•d `F’Õ¦ú4°2ëŽàiEл?§8=F5óB¦3ÌØ"í»á¯Ol¦¾ÅDµv¯yîboÝIw0<¼"‘IÅ7æ¹4Åd«32zÕëú³&£³žò ¹{é ·t®€,u^Jamì‘Ña­À«3]ÃõÉþ°(qQ:¼º}ŽäR6 cL‹ C² ÂS×Ë®g d„ûPʘ}gà {ô%üëµ§­ÿÑõçSº\…²é“@' ÌîO±(ãÍ+ÂF5ª\£ŽU2$Ëq¸ÊÂ×7¶d>}–ûìkõói†Ì³Þ‰#âÛ¨JÉX,ÄÄ:ISÝTÔ0*Ã(— sð¶ŸE9£‰7Y¾L§á`¬Ê϶Y¢@ËN½¬5(xÖæÛHûJÏXgÏ_«ÁŠÀ…úã¨>¾9ÑNýš^&TBJÑogL¶·‘EZì+f¾ S”¸š,úþ=™*ä;˜/-¢wOçTíêÞƒ$‰ò+ª…­áê6pÝóÜ:ÒLÅ×A.{ì"dûLpb✲ëgŠyÊf–d CÎy”˜“Ó¾çéT Tú}‰ï0ÖBÑTÎ`½Q÷Í^|›ð Óx‰Âš¬cy-.ϩ͸m²šè ü†Ÿ»ï‡9d®xÁÜo$À€»µ~‡æ…g’øÊ!¤È°ÛÝêë ÚnÞˆDÊ7£4×?DhŽõkoCŠ*ÄkNù}Ó¡¤oÑ÷¸˜µ5¶=‰—óž/â€ývT­rÆ)çû“"k'8Aßbß×Qóšq£.}¤R6=‘„uIåÛÓ¢¬éd$t9§@U}“ccÝ¥MdÛåEÀ%¥ñT õß ²]üå"¥Zß?²úçtî|;uøæ@Dò+pðü~Ö~ñ3¬ÓfzÍ%y$ò w3â¶ÛÏU¢îHx]:½Ó2Ӳб׻™P¢×àZ}ÞXÝIãVhX$•n§È—ýôãÅ+YºÎÌø£eèí~¢7ää$U#EÚ3SòC`ë¿~”Æ_Õ¼t¨,CáV^Îè™àïÓÜ)tDÌ^üÑÄkÎ;qÏT^Ã#96 }›æÃÍáUåë´»õ"iJnɺ•w€A?vgàp1'õ`^ßñ4ÕÇ£×Fƒ©|«MË1Hªê‘s>{ú²œí§æd’Û›õD”Ýmš šmk·ž"œL8 5û,rÿŠMnÁÒ5ª‚:øñÛØRB :ž2hJÕ­Z¿Š®t/ZÔàjöë³G¸ÛnÁsüc\.š¶ÜDµUnÀ|?H$®àÇÛµRµÙº~I#XZC$y§:‡úÞ§™u ÙïÜŒ}¦|˜}äÏ›:¦5+É‚wƒ–°¨g“E’?Ïë\§%÷”wÂ5‘Ô„É¥õćP®T 2Ä={6tGÖ„¹w‚1Upñ˜¾y¼=hãLƒì夋5[ó.ÓïçsÇ6 וZuºÜX>ÌþÁtìS{ÌKmƒw˜ZLö<òzqèI$L4üú€—õþ0™Ý™oùïÎäOq_î £ONåÄRÿîziT’W[GæÎDÚÙÍ~DÔgN^m»ÝS#ü‘c±®ù!@~@ì4Y/æVæm« 3ÄW%ü^¯ú•)GèM»W6ⱌ_èB/;²´­«¼åñ›ëUb´= #¥xäyæYÿÔôlØðÀüÆxaÌvÞ®§7#BdáË ®lÚwå/q—•°Š¾ä…c²XÔv‘±?Þ.Gõ›|¯ª×x߯¤" 4×*Å/äë‹ õˆ>Î-¸¬£BÜ/Án lÔ3û‡ŠQ‡ú÷¡Fáïe³Ö¿ç-<ËsO€¥yˆ ‚Ín»Û/îÂýÚ‘=¥Ý‚8Ò¢âæ&€Ó&šGZÛ8`œÑ¿vÏ=»YnK©z;JKSôÝn„P²ùîˆá°X \Q>JÙþ‰BE³Û ßÒMn¶4eyPì0}Ëõ¡ÙÈ{à’ð-ÎVAøãÚü³ÙÙþ«‹WZkànmÇMb•jÂÜ»8œ€ù²#)À¨]ÇjÌ+tY^ÜïØ‡Þ 405*·:"î Óàû‰y2ÝV”Ÿop-ˆ‰§ÖÞ'/}׎®×î–ºÇ'ùئI~jÓMªvÇæÒ9ªåÊy ´¦§3•ò£<ìòèµ@¥`ƒüˆ¾üd ðâ«ëªC\­ÕóÀãvÑ~à”à}ù4Ë4OÃØ‚UÞµDÜÝ9ÝæýÉSEÜKþ]P^?ÚÉ=d¦Ê|cˆù›±%‰#ÇžoP»RdŒ#W«d€Iýk躾¼È¨º1 M&Í gëߨ×Ùì+MÚ-¿*^/¹šbä]ó)ê¦Ç›sÒ¢Ì8´’ÜÝà Ê©€ËÆGù§e¡ê£òÓ”`Š$§ûÑŠOm&e)-8,(·'“C…ÒNAm³ÈÈTùYzÉù:)&L2ñxìÙ`„Ì•ÌEÆtÉän«:grÞQJ)Œ—ÃhnÔ5žä‰·;ákÞ=¤œy›¥„ž§\üTuØç™i€™ FÅûf Ù“‘=‘ä¦êÂ=L’CÙ‚·¾dm,¦, ¼(Žܯå’[ëA:zv1äŒÑuÑ)^ð 2¡rÎè„ ZÖªäLéÅ;ßSW®Þ=suåÈÓÆÀW¸49îa§FVy"€'xûÑõEö¾JmèmÑ/ ²`˜çÇ&"ªvçC7Ù½ä· ²Ÿ5N>ù´|(’£3ü:†-°³£O¸Át¤¥Ð¿´žld‚ì”")¸J§,¢ ÷AÃÚÄ"v¢ðt ØmXó$YsØskÂVä[#W/a ¥<â¸k¿»“üpÀY Ê'/r^/*ÐvIBpZ€×ˆ† ŽôúpÕº7ÎÀ¿;ñS/ê[ohAÌ?>Ög4ãr`"¿Û­½ôXPý©Øé I™¢å™b¾[9CžšU‹%Õzåà×éÁѭƪrIj ž}†L|ðrãKúN‡O3ãÌŠŽsÑÚgŒÒ"̰{ZÌôå5áigϦ+š|b—oeݼC®>‹¶k'¦h$±^ð ® =Š’­QÅïy÷é¸ÁвÄBvÑZøù¾ÚÇ"â–—Xy£v0Ú$_+ˆãñÝ•ÕþaÙ·À endstream endobj 88 0 obj << /Length1 1373 /Length2 6090 /Length3 0 /Length 7029 /Filter /FlateDecode >> stream xÚvTlû7%1:¤‘I(½énI ©1 Øcäh”$$¥Q¤¥A@¤$$”.%E@RþÓçyß÷ÿ¼ßwÎ÷³ÝW_×}ý~÷ÿuc3QUg´\ ŠBÄÀò@uCS ,!‹øùÍXOø_Zÿ8ÆFÉÿ/»:ÅâuP,ÞÍêùz!@ˆ´©ÍÐ.X(Ä+<08Êà‹r†c€øÚ@3]àm/8ê/gƒ¿D€_ "ùwº¿£'B þCa04Ò Š D \.O8ð¶–6+„¢œ;B=}Ðøx¨á uÂ;üi ÔR5Bñóý= ƒðÂúˆù <OúÉš(gu4 Ga}¿ûÓ@`à0ü­‚þ¬Õ…öGáþ:» PÎ.¿GpöõY Þ¾p]¿=ð*Àt®p,P ËÈpo <æúÜ<Ð þÇù­Æ÷‚óB{]ð#ÀC.püçõƒ±_xîþ)  3†:Á](À²ãÕp—¿düæ1ˆà]0x ø÷çß';<¶œÑ(ÏÀÿ¸ÿY.HËZ[ÓØBøÏÀÿ6©©¡€8Qq ¨¸ˆ‹eð‡f1†"þîüŸX]” (÷W³ø[úWÃ~o_àobÿ™ËG,(ð€Û‚¥À0üäÿæBþoèþåÿðÿîGË×ÓóUà·ùÿ°B‘ÏÀ¿íx¼úbñØ7Dã€úoWKø_t5„;#|‘ÿmÕÅBñPE¹zþû>Zˆ¸³1 sû *é-~Ì‚£}¿ ( þ/žU0ü£áƒÇãOš–ÔDÁÐοÙ%.% „b0Ð@~ÅxI ˆƒàiè øƒ` H …ÆâC€øñB€.h à÷>%å€ ü³ô[ùGÆ×aýÑä‚ùb0xšý¾‹É8 ‡Àa€éI4ìÖ=÷×÷ÞW«rø‹®)Žñ¯Zf Šâ¦1-¾§4dé‚/s"ç1GªéýtŸ—5Uf¸/p›oÈbšRMšÏ‚ÏRLGW›S#ÌmªÖôpQpŠš«¬_x߉ð n$lÓãÏ÷ö•¥1.d<öï֨驘ý=¹j²öRZŸò¼â£h¢E‚mDé8ÓÓ VR¬(¹Ã^íøáÑCÞð%·^Š0 d+Q¢g³ žt2ôå¹¹¸O;› +ñ!ÇÑ8µ =–O¸²â¹¢q[ß’8‰ÏívÚ¡“K2 ˆÙWÊ}Ä××\nµQ6  D´c«f2ž­]ˆT†UyI­­ŸƒóúÂèvp“\ u¯yÚΟɨ¿y|uI:.\÷:»¢âáÍ4î=̃?n¥ní¶ŒªëÑ jnj-Ã7¡=. ä5¡Ä\žëˆòŽ<€~¸£UOÑ9…sªˆž}eí}6‘½a»HûB@Ð: ûG!ŠýZáX·ò1"÷Ûþ-Ÿ½·ˆ(öÝq;ÑæE}Zèà¡5e†Ð rz-i,˜l%mÕ²ÇÝš²“r1Áþ¾êµSBÖ îsÜZmB‹8½×ß$)¨UrÂè×ðþèI¸1ÕÕ2æ©äv/„GJƒ£ûîÄÞŠc{vm‡f¥… š|ç[­å¥»š‘˃ŽÙö†(ã~ó„)Ò¦’P¾Ý¯t/¨û}5œ™¢§$’LÈ2ÕØlÌ\}%©6rË:JšçGN~å%@¦8>.X-z¤Ë°Œéf7*ñsœo„Œ…¦nήš?¾,½Ê§Ë?té½ðÈX—·FÔ!uxãN€ÇMg@Ï–ÊÜÛñÙF›y=i·ðÝK3Šnª3ÕóCHåéÚx“ÑN“~MsL`x«í÷mÁ6agA8µãÊ!Ìø¥Z®‡½Ð…@qþ¸Îÿí‹ö“›¸.ȧvç!Ð@+LkºFÕm›ä2Í~±áäÏŠ›©üöe- ñ;í ,‚ ­ìO¿}ìé]˜ßÛFî6±¹4±‘]aà4M³:ÎÅÕ› @„G+&ŒIÞsFRéOr!_q¿*ÎÙ;Ÿ¢¶ÿÚ0é§Zó€Öø¥À]áǹµmU¯ JÔÿÃòMÞ3²¾Ó ¥€õΊ¶M©Q’¨´ƒÝëþcö_S©N˜¦º‹§üÒˆF%ED‹"áßߎ5‘+ƒLã–·2•“4j¼áÞôO+9ÉkD òËÈ4·w€|‡Ÿ³™“ …$Ðo«²"­Ç…Á8a#±Ó‹Úð¥áØØ›Šùõ½ºzgœ]»1ê<>^¨Èê|ñHNâTQó|ƽj“HòpÜÆè½8€àå¡~¨D“ò/Âæg;¼oò£Iä*ØoÞ¨^|bHC)òÙ¾éË¡µ“3Õ+~_ö¼: )ÝIªpÇ^ß“˜{(èÎÃÀŸUÏx4‹eiµéŽ ÖzVºë»[ÕbÝ[hÖ߯w™e9&ÛÚÓ²_>9.¶ËåƒöXÝ4VwO›Ñ&S… ä¬ùØœÎ*ê> ¤gíÒÐæ}ÚäÔYsýärNÛ%¬XA¸{]øc—*ñõåc‹ôYJÅ»4Ú_ìŠú¤ä^?© Ax•BÈÎòCyÞ·g{(èìrGáé¸Bót‡ØY—!Nv‡¡½”éíV¢ì»˜å¸WCéÇJ+•´Ü’7ȵ{”1ŶÁÒÙe4û áþ%¬)Ÿ»²Ô„1ãjɰõÙÜ|‰û~€ìÌ…ëožËƒq¾l€k]…#ª×ÈfÝCpÞ–öjå7Ÿ~¸`dµ.&èsC'-»M7š-*ø2œÌtS]meÚôpW×¥Ç>D¤ Þ,O¼Wœni˜ÉïÍÜLÅÕú¼TÜ@ÚFFD¦·ùÒ{Úk»õqO‘ªœm.pf&ûP4ŸJ_Mæ|Eâtjq“AèyÝM⊒éUå•ÕMT›j~#.'·ú1·HócH,.[ó(vKlÒ4i$ÉÖä1¿&ÀDàϘÝè)6<¡« nË›][´Õ$ˆg«Á.7ˆÞÌ“?>ôºØÄn~¡`ŸGoÓ*q¥¿ ™/ëÍŽÚ;*w5WŠeì`Gué³X5ÇZv(ãì"]zN×ï|«šH­œs—¹u€ö·ÿ8äÅñnm³¬•rˆFœ^ɯs:ÝΜ½û]~GçÅ[²qU+¢ÍÍæ´îËÒŸ®y µÞ¥l]5j•k“ï…ÜŸ5Ñ»ÑLê&ܤâ»Òª2#‹ygòWxyÕÂAÔ¶._W}õ`×2[hôóV÷ž¸¥%úØ!‰Ò¤¨¶×…x0;Çõm ·lew¥|CwVïÊs k«‡Ë¼Öæ1¢ŒŒ±‡mÆØd!Ù2U±*fÃÁ[GÃyÈYaÅêŠ;ÝŒ:¤–ùÆ# ûÁgDù^ÈÇ`žæâV g™õºO­l}wïXå•`[^j½o ÁLÔ6Z‡æ½au™©m™à¿ÚuÄ}x_ÛpÁ$t\1Éx`WcØ“`åÀ€ÞÜ«×ú—Þò[¬lÎä©üÎ<{ê×å²yù‰SàPen~ÝÆ€­”¼œ•Å(Ð=žÈ4{Þ•×n—ÈÒ»6gצ¡,e¹9üIÇjl,_øéÆn Onùækw^áÞ¥Þ>ÛÇ“¸ÔÁ´°ÀôõŠt»‘ÚÛÇ%ì³þšðG^äwÎ~œ_ŸëÚÙ8?_Ï×Ö¢[לïèñ©Tï>¸ÖÍ’@)ô­Œ½5;Ðù‚ŽžJ?vøú~á ¸jcSâ˜ØÛ$SL«ÊËJ5£@+ä蔥Z =]H‚¥Òø˜xÐítï5’ÒÒ0ïꨢž\àý_ÝþÐþÏÜ|¥J>kdsÛ‡E¤WÀÕÖ*e'M}eR§åtõ8Ý–¤)"%ÆWÖ#_£GÔß|ÙŠâVWlW;QÞ)zÛÁcK_ èpuè ­;ûé-¦ D¡? gšKßB([Å;}Œúr‚ý ÏmÿEÌJ4>sYo0 ݼ‘jàl3r mù#›^lS²4)Jl§ÙžP¨x„«†y@c:x×F¹fûžÌ½$KÈá *!j ãeÈ€»ÝIÜe^+ãqzþÒo”¸¾3i°ç);\îbGЃ?ôãÓ“ âoÂ*âë¹ç(>sÎÇä?@²2™‘*1uˆ>M˜â NI¢º6´t×B¼:Sø ÝñP«¢‚®B»qî½ï¹3ùEKxÀ_‚ñK^抠©-/WCÉI¡\±Oäw«8ž×¼NK´þĸ\A´V¸Ñ ‚Ewò›ÙïòMâÇS°Gœ'âŸÌgP¡;bÛ•QÀ{méÁ=×÷Xç“~y ¼ÐºDP˲B¹çœÖ'ŠXÜéê®ìVKîƒÝZ&Ó=ß½'ö[vodÄy£_´Åì=È0­Ö›i27KU¥ßÎÙµx/¯Œ~áMUCgiKûëýÕï«ÜyÞñD%,,Æóï± ‡WÝ—k;{MEü^Ê< Õt"ˆìYk²‘bRd?TêÊ>É${¼×3™Ãt\Ä{µÙÍŒÁTµfKI¼{Ž4Šüö„²'-÷œí¨Æ·ÛÑ1‡¾‡Ä’!ܳ½¹¼åTÅŽFm±§`£J²HºfõÕçÓj KŠ•®›ú·i  ShËõíë1㩎z/>±É‰Åôš ”BÈÜÉJ¾{¢2 j~:žºœ 3‡WD²¾˜ ¬ðmŽ×{åî¯1Ì ‘ÛëÓ··”1¸$¨ýØæ¡³!‹é cÙR%0÷’:߯ü:º|‘ªå^4ĵËÕXÿÑéû•:ß Šº³¥;ÎhóF‡JM¾èÒhà(ƒúf„Ó7šº¡‡É¬‚¥¼¾¿àE_È6„ é¤=!¤—×Bâ(„Ù¼©‡Ðé¥ ‚¹nERÕ 9òñ›“êN6 2¹’_q¨|=•Æ9ŸÑÄõÔèÅÁ©kô^LuЉë¶ÛíÜ#n­„ƒ™f&â/WÑÔ¾6³†­$~ê¯ Ì£Ñ#Ì¢–¸{—‹åuŠ=“þGb# >=¦‹¢\±ö‘ê¹/. ‚’~¥ÎeÜÉsmZ¤ Ó™[{w·÷Z§ ~íÇ ·¢p[¬¡<7ã?§as›ƒ¬:®‹YßgA‹Ôh'ß {!‡¤“зYÛ/Ì»|,È6nFd·ÈjêxߨjK«)×q÷ô‚.áö×™n”ŸÇ9”o gÒL«¶vè”t옇Ñî麵j÷#›Ò«¼€3^Œ4×åê±"ÐrØli ÙÔ£Œ‰ç…3îþË€ókbôgÓƒRk”°‹…ÈÁ™-Ïu_‹2–)¾KÔ3 &åCÉ)!’1ôJ6µ6Î~Û…ef‹¾R%à|Ä*\-¼Õ¼JÕ— é#^8ÚUVWÝsª½J`uÿ ½T>&gb°^pÅj¬å¨‘dK’{uÉægÊkÁçe½"KîÆÐøm¨äi¾{£Ò·P¾_ˆø)æ‰ïŽè E¼bVY-F] åã:Áqto/gÐuìxõº¼B3hFÁéõP%”òG`Ðṫ0ÃküœË á§ã³ -ÉÔähÅFéçèWeÏYöOžMÐTq¹Œ:¤&[ov€­tÊù%«… guˆ±þÛ¬À‘„Žä!'žá?ºgÞBCÕŠ.ì`)(œp.ËiøG:¸«ìI4ú¡.#dŽdÙ–™ŽØ­‘ÂbÔ¢X‡p »üaš®A¤Éäyb›àF˜ÑÐPÙ,ór…¾%¸[â°L-äx»”\^ê-eœáVî“å”àãU£f‹ÞŸI›×yç©M>¶ÐªWgäê¶C×Ð?)Á¹$ñK|úFTop€\NSìö„ܳE²}Ô8¹Öé ‹> È…9JÊ*~¨|î"çU†”M•¢³êcu%úF—%¶®í\¸Aó œ›]Uoý*¿$…ÂìHh™çØ$£ƒøÀvše­{E³³áí®6î‚øU³Y$¼œ£“§«ežrX±IX!—ûáÒï|?Fyžj5½`ÍeBªÒEd—}ø†ÍXÜ­ôÉr3RÐê»ßl[ª5 ÿœxZ¸=õJ?g^®Á ¢ƒ1¡Jˆ©Ò±I4B.üЏc?3{—µÊ½gäìÎþK¬mÂÏw#ûÚízQ.žl[«­›ª÷]\” Rêt|åÒKž®É­éuB’» !Æ,Îe>ÃŽÊ’_È%g>²šÔ2>p |mÒS ý|^K-À±ã/kûõ±­Uî²j_[v˜d¶ã»—ÛÁ©~ÑËQ3â6Á‡”¹÷óœ[¤IÄd´š<Ô×@ )=)çì5VxŽv׫¸Sö(ïȪŒÆpîE¿HsŽùöù\£Þá`Û~âwdÑpu‡-¥.F>«CY˜Ú~ÃMUq*ÏäÚk£w Óš‡¨¼’Ó–dÈ™ZõÚ×Ç,#9 Ÿž¬w®‹ÒŽ‘kz¸¯ o~F¢_vzððP³ê¾ÜXÞ­ ¤õlùzh°‘†×‹LsNsiþïg#:0ºó¬{Å~D^ÎŒíU P] ÜÄY,gÊu7û]¡D×höUrz²b;…@îü¥}M墄Ó.¿» _…¡sÝŸ¬À¦Oêã÷–°ëË=yñôQ£ûÞô$ƒŸ%³“ù ew¬ýj:ßéÔ‘6²˜#Ù´1”ÂÊ+Ë¥ûW”–|p{7ê«ÊU¨­‚è©VÎ^ó®0èèkð'øÙ„ZÞNT¾C.Ñ#AlD©u,"Gn„,p—‡Š§¹ƒ|ωÍÜÌÀMÿ’0àf—y¸îšó´·&óí¦)‰£‰¾ì+nÛã½™ôp°Ûaþ+`¸BÕ¥,SÁ}êÀ¨©w¹ØÛ·Æó'[Ñö/z!s÷lïóÐU«·j9íþð44! JãnX*ØÓ}IP-ÛàâGU):=´@Ä?“[|;bLÍüÎ#òYkáv/½3À|ÿk¤W«›DtY¿õý h¡Õ—¼N’Z!3kƒ&5c‡»‘:–$j Ý&®.k@ǽVÎPú²¤­»f‰‚Hˆ½–)~ùÊ¥ì ¶€÷ S½«¾#^öÝ­*y}ýG$—èD® …B*¼^tÞ7JÁ5»äk†Çª¸å/¸Òˆq9:óôÔF1°–=ÇP.­ÒO±û`š$¥ØÌD»,˜úéXž-\:~Ð⥙_mKÆ BôCL1+4:JJù9Êùl7ù"P~g)¢8{ånÈ2¶Éž½˜ñ Nâ‘õŠ4'ÚÈÂøB‚¼‰6R¯M¿ÕîT±.XJ¼Vs09L,ųòƒhnðWý'×qûG.Y›‚í,‘DÍæ¹ÝŸªoà·Š;¸óBËôÂÃ޵=ûôÄ!á &Ãm¨ØeE4†íE³¬¼†„1RTmÐw$u»[3x÷Ÿºtˆ®GBˆ<vMSãŸìß¹R´.ѱ¿ì$CDE%~zßKg·ð?Ç1P endstream endobj 90 0 obj << /Length1 1373 /Length2 6093 /Length3 0 /Length 7034 /Filter /FlateDecode >> stream xÚtTÔíÖ/]Ò%È€Ò9H#ÒÝ)Ò 00ÌÀÌÐ-Ý-J#¼tJK·€¤€ €(Ýߨï9ç{ϽkÝ»f­ÿ<»÷~öï÷°±èðÉÙÁmÀÊpŠÈ/( PÐÒ >â"bc3„  à?Z"6c0 Ã$ÿ—]¡Ð:E í¦‡ÔÝ¡à#PT(&)(”ø—#! Py@ìZüu8 Œ$bS€»z# Ž(t•œ¶\ „„ïïp€œ ±ÁZ ”#Ø]ÑÀm!`”÷?Rp>vD¡\%<==ùA.H~8Âá /À‚r胑`„Øðk\€6Èü{0~"6€¡#ùGm·Gy‚`Z…Ø‚aHt€;ÌŒ k Ô4:®`ØgÍ?¼€¿¯äþ;ÝßÑ¿A`¿ƒA¶¶pWÌsØC `€Ž²&?Ê Å Áì~9‚ H8:ä‚@A6h‡ßƒÊrzz¾¿§CÚ" ®($?ý5¡À¯4èKV‚Ù)À]\À0’èWŠØ}ëÞ¿×ê ƒ{Â|ÿœí!0;û_#ع» Á nî`5Å¿=Ð*¢ÿèÀ(€ˆ   ˜v€½l~%7ôvÿ6þV£û÷÷u…»ìÑ#€ý!ö`ô‘/ä î`ßÿmø§Dì ¶(€ Ø#úOv´lÿGFoñ˜ ¢þúýûdÆ–õþûïå èšè¨*éóüøß&yy¸À—ï‘(€OHDˆ¡þÿÌ¢ ‚üÝ…àbÕ`öp€ÄŸfÑ·ô¯†=þÞ>çßÄàü3—6X0€ó?7´E€ÿß0ÿòC÷¯,ÿ€ÿw?ÊîPèo+ç/óÿa¹@ ÞÛÑxuG¡±¯G3öß®OÁ誶ƒ¸»ü·U Bs@æý÷%BÊ/°.eëø*ôF¿…ÀÀºp$ä׃à þ— Í*[gô£Dãñ· Œ&Í?K*Áláv¿Ø%$" ! o"ôŠÑ’Àˆ¦¡Øë7‚ü08 @ç°‡#ˆ~íSX €~–~)Ëè:(Oøoù…lÝ4Í~ÝÅ¿äßœƒ½À¶Dó³p[©P§šÐÖ³j9O¾ÍQé)¶Í§\|¾óˆ6÷ Rü4®ªœç+ˆ¹´Á÷äŸ>+qË.0_û~kªÃhNÑk¹ô»²JÒŸØl!ú8NÛ7öú›\m/!#Ÿ¡ì–ßµ›Ÿq°3vf‡:[¾›»8©nÕ™gŠWmoÙâpøì¦ÞV•¨Æ«²I¾8£Xóàâi¶W6¹3t¬x(>&nÊ/²éã“)Ê—c·ÌêICÛ6²æ’ „nsúljëŸ!v~Z²³IrÒÓ `S«ÅÄ®4«&»³$ã ç|R_ñRû)ÖdƒäÕI†Üê@ÅjH­z&j3Ú¢R[iïuÓƒrÓë+ýQ”^u¼jêÑzžaäí~(·ÀûIt)ýi/ ¬ž9“æK®ê:*¥J(9Ì镤+ ;x™z«™Éð³$ÎàLi³ÌÐR8˜Î€ç§ÛíšF«m«CÓø¶Rn¤øøø|µqßçnV.CǤ¢1K 2/¬tœúŸ½Óx;‘\<ª+1RŸ]0Þsß•ùòD5§5b˜M;®EJœÃæp@*δ;­3Ŧßn•IJû°²ñ ù(rD>IEæ7ô,¯…(sA%ýïßV=Ú0!JÂ%aÒò8Ã.aSÑ>hŸë½Ë;YÔ&`=uÊš½‹­ŽKž¨#ôH|!‚ˆå³PSyn»Ñf/¶1T4üShnä^ÒB¡¿!€ôæKIi·ì!!» 5íJ-¥¸#Q(ͼ¯¨N„qE3¨Æ“#GZ§éH“ÎÖáLwýÝW$‰wÊCÙ>4läÏËÎ(BÁ~ב:éS6û!Uôí/¿~5&,Ö YO¶ljì ŸŽhyÌ¥UÙþù1–Ë N\‰Ôð—IŒÉd•þ:v@ SƒQê/÷]tCìG„«§›¹˜2üµ¢²u‹·„Æk @‡¸áuåãÑ,ÒïË®$éÆ þ?c}ë‹›QÐ0Š@Ôuž•=™Á¦4‰¦4mg z¸{² Iþ.†¹ÐD‡¿mš‡ÅXº6¶WDöšÏ(L±kÂEëÑhÝni(Áî9}d{aÓz •1ùþ,¢ôŨ™¼eæÕ(ùËÇ»­ëõ3ü–ÏØße,†3&—$O^“œu·´'5oU‰;µûЫM-î(¤³Á[¦®Êã³t`â ?õ¼Rl}1Ä7N.”Ä©Î2tè7?ÑE ’“R¼=³—ózÕYb¡f6„úì]pâºD`@‚‡—Ïæ‘g“ÄÓÄ31,ÿܹ¯‹Rнo>3k…MŒonF¦Jïy_º^t¢æ.ã£~X]¥ —|‰N"K’#¾Ð²àMëd Cæb.ך¯Êº"&zФ–˜“ ¹B#ó#ŸÁ€î¯]íÌö‡ö Î]¸,PýÝ ŸA1±V^a”­ÛV÷ÞÃ36û~‰—¢jzwªQu‰0÷<~ÕšèζoU“¥Lby§[ºp#i›:m:w \!ܾ-ƒon±¡£VÿIëz´6Ö(Jöh¨¿çqS„¢îŠnuß§pk#Eq",ƒ“êì_õU’Ž@i CF)(¬ýØ–Xšâ°ka›ÉæD5l¼ÚÍPÓBÏ<¨ˆZn8ûl¢o²Gk$åX+>- ^ÎüÒK³¹=&j2À}ð¾EH‹ÕÄÄÂLj‰qþÁ2Ù©†ûY 1ýð3̾<µ‡ fŸžñª†GS¾iïU[x"”5OÌõ-ÿª¹ôíÝŽ7u½>1^±¢E.)a´ø&'ÊÆÑ©' J:^êáDNÊ.E¡Ž\ô&ƒmدgÆ#bÄëCú™bv^ø~vÇï&‰ ³-äÞ”*Ë,Øl®ôc@+nüNG)d_÷LðQ0:}“³_—ø«ÝøÊæèU-!¥8–áå¢]0ËŽqksƸæmê1mÊ 6.š Ç‘$2ÅZÚ{Ú«òïÜãvZG°³ß7Ym&‚ÐŒðw#0<ðpqR˜Ý,·Ñê¡”tÈ[ÛëêŽ8!ì1ÖùF Ýú’²PFv¿òß„·Ë)ŸðïМ;öaÊ'^O/HãÚÊÛþŠsE6š°Ä‰ºñ%„j‘qìS]¿êMXXaö÷ñ6#½ÿR3(LÇÉîÉ9£4¾eµÜsÛ|”£ôÁÃ/3“§ÀÐr_ㄯÀY&öÇà÷¬©dþ5);_®™5WyÇ»<ÂÛ îF„w¸kÊ·±Ö$/\RÞH=fbC>ÇÂGôf}PÜ${„Ç•]øÄ)“fƒ¾þDDzøî¡«Gœb˜ez"uO>slÖ"É‘×ÃŒ¿öxì¡G^ÉIô¯¶Äºª¤×é¢O4Z >áÕA‹[’ô“Ì0…¢å¡OÌT_»…èqûš­·"2ŸW¯Àn´gÛø]ÇŸÄÕ­œTw ÚΧRæõ”ÜíÙ¼Þosº°`bÊßá´A¸=s£wÇ´-WerèŸïÁ {í*–ŸRP)ùN{^OŽÆ³u/|fæYÚàïzΜ~4ãï­N †NÅA)ÆçlðV#¡x–ŠÝbg&G=™„ÃWe\[Ñiìê¯î3SSMñ®ö/:Xаî*»s|å^4ÉâŽO€”A#~Øk§R¥ûº™2Vq`Ëö¯ÚáœÁ L¾×¬=ŠG˜·½Y„³Â¨EÃg dw%²nMü…ÁzÄÐ.+1ÙT SF£žÒv7r¶ÍÜãT¥r]æÂLRÚS¾uxÌ·{¯®pDŽ+6:5«ºæ¥YŒEøï´çú#05Ö.™h߸=ß0ÈÄææÐ¿Î# ’lD)cZùëóÑíÓÍ“_g)'IÿXg’â6}ٺܕM®Ÿ)ÅÏ)òÊ=ÜŒfLŸÝ#C¯¦»—~ì}wiZÄ'Iæü*屨†{lÖ¼.´åµ¼]ò-ƒÕu$#]ë ôpdi+±ðÂt}æ%-Þ®J=·œÆ­?³ _ý(ïUª³û€¼wÍž²êR ê®&è›ÍÍx@êfTfÖã;;Om˜«-¸ôâ(æœìaø C®ŽÁ䛨ÊL©QóÄO±'â’_y}#kj¤¯±ÕÉ”B„Ìž¾UlöUìûÔÂ$ÑuÂÀ¡´œw:¾yùx4tJ—œ€ñãªðÎõŽñ¦ÑlRB‘7Z—ž+«Ýª®&¨2†Y'cœdyä´§}+Ý”f›âmycj„'DUzkÉŸÃXÚ Ü½=XEÞ-*úÍbà¾7xº2ŠªçGÂ>[Ò<Ð9ÕЬOgûÈ™}ªu^=?ŸXØe”äÐìc§YÊ€£ß¨S•ÈÆÊ0‘„zý@\Óýã™Ù)"ÁJÒ™Ï/~nÐwY1zÂÖ:|wZõäpaØÅ¥M*)jª/b-ð•HΫI“à½Æ¹· ›A­Â’œCæŸ _?cÆG>î¨Ío\}Ñ­Ý$³J¤õr€xd‡£úƒU=_–!;Ž‹‚¹‡ëÓY™H}U¦Õ,½ Å-¿»œöÐÝ÷ Âo'P²WÛoܳ ¶¬Ÿ­LÓ´|»] :„ö¸­Ut&¼UþþZlŒ·Â¥ë³Rñ×FQ‰'iSW%bªá÷äÒgèÚÀG•¾ŸÇßæÇÉO iòºêž¦,CG_Þ±wÈ“R»i[éJ“)`Í\”ŸšRô¯!ÖÜÕzB¤´ÄÛ+l[4Ûå·CtÏ?‰4’wSúâK5uýˆƾÐÕ>Vkô¥åæ¾åÓS#9c±·^z`šûJêÃö"˜úBÅÄNÙËý¤uÓ0Y,e²é,5v;¿æ4ôƒfc>ج]™kXp¦8ÎÚúHýxŽ>:4„¤"¨9 Pá6!€KÞ@›¼üHf.¡/+ w–Šê52±:·'Á Ðß8GŒ'ù’ôâ0ØcŒ@|#bÉyíSé–º—öü½Òb¦?ýC(ûsêvò,l_}c™u (‹“ñg§&·1yÑè6QŠyt›Ê+Éåz4áüÒTt¦HéH¬ Va“GR#iúkTÊ»µó¥e;m‡2 ÊhóÛ v2ÆÈ\pIê_»‹c˽‹!@ïõڻ˛xåÔ‘ÃÁžm Pܽ­²ŠwyÃn@å.=û| ÎjoKLš„yÚ÷¯²ï[³¿0c-lröF2Ö[Æf1*1áŒ×^³5¾ã$¶W÷‰þlyÿNvGZm ÖA‰> Nh$!ÚJÛR°ÿŒ’t6Ü´ñÕѵ)cÈÔ„C˜]7¡‘Ä”Àg¿WGSÆcm†V”´Kì÷ZeWІI3/}¨FUæTÖ¼ú·‰°¢Xkꋪ”Oá¸%µy¹“âªî~Ù‡³½Öî©@5ÛdÇr²joS© Xæ¯z_yecvФ¾%^œFw ÆÍÊ΂4:š[AyÇþð‡¯Êù~Q‚Œ5´üewWH¬»ŸG¸)]3þYgwžùI©R!©&üÀy›ÿ:²gB;!Ž]Ö“|Ò +Vâ\8t\÷âGuøÀÄX mz}šmNvà¤-ïN?Œø(³³½mŸ•‰ûø¦Û‡šS›3o´û² ;Óz?‹“¯¥lÒéÅ…èt ·Â`VÉŠen"µ êá„e›þÔ­ý$c¦a~ìf·6UøÌsÿ„<«®î °/„G¶l#ÄÚ¿hÆãÜÓD¸;¥‘M2Îs…lFòp^b*U¦ yµRöªÙ69àå Ãü¾}úÉ$Ü“lŠ•ô¼£µíF_7(çuûº"ŠœðR•%‡k—íïáš9÷µy:t5×¼I b‹¹K»cºñ`U¦ÕÿîG̃í ܾÈ#-¥EKqêi„úDärí&"V”i¥J|YÏ‚¯c9(²C"UÔ)ºÒ7Ý£6”›éÂ×ç%{ˆ5µø!9iÖ!„ÑE«Í˜ 0oó"ƒ§²Ø’]À3{V¾£p÷_Í}ûö vß ÚJšªø—ô vÔ|Ó'n`ô#™u‰ÒA„ÈäAUÊcï¿ÌmŒͰw!ºí}¦º¢>ñ ù“ª_‚·!1+m¯¼Þú%žôÐO=XŒ×ûÀX%cpW/ú¬ð³¨QÔåÀú§jœpAežÀÀRßQ}ÚzsÔJ¨rKC¯­ˆŒÜì±y­¦3PE5¾ÄõÑìä,('vú\ÌW`6ôÎ8cZ >,ç“îãÙî.hAåQ «Áö‰¥Pœ†g„Çô¹œ”Úòä¼t}h÷=,°J‰ÿ\Ï"aÈü.hRóÅ;¥LRÈŠXkã:‡¯2£Ðµ÷#Ù[Ï\“˜‹Áe›C‰³ÝQiV[Ù¶--òdÃüÛwá˜ò·ŒQ+Bƒ¬ß•¼^ÖȩԼUâ–ßq)eüäy§`É–w°Ú‘÷åãö-^l7<÷W4E„óÓ¼/w:ô1âħ ãÃxÆñœÊØÚúÖf/ç¶»n›/Õ«sƒ;kžW“uo~8¥ßÄ?UÝMlý ÂÀ/í˜DÃ"fv2kÊÄ/ï¡!"ì0RÅ¡”zºqR´²t./A,êð>f@Æî¿7¬¬™-‚ú›lç¶ÈH©öW­0éêp+ ³YMàëyGQñ‚y€m˜!ü—ƒ¥FFÍ 2 J²Øîâõ¾ÖcÆßX>Üc3V<,ªˆ‰oΦ ŸÜjòÞc‰”¤-v²æ/enHûÊy.QóiýÊŽ¥8UP*!á…€fOÌá“nðu»x‹\'xÒ>|\å·åõvLgEO¡~° ͙Ÿ•”T'³Í  ·¤“¡ÉCÔMk?¾n&º_~5*õ^•o‡5$¼×ЎʽÒaºŒÍ]-áæM'}ë6–q„ë‹x‡Ê,ezä÷4šÞÈrÔíótºxgˆlÈÞ—tÍ›¤é=Ø!pk1²ö!Z%xu@Ï.;R§’ ‰Í¿9“Æ­¾s°p ÿÖÕñŒ§L£o1;8!Z¹»æÓ#Ðà£ïxnáÛí–xôž½îŽecåtÝÔk->ÉgÕ×ëÜ)6pzE ñ~ÙÚFš©˜” “åu`ø2Ù¬ÅoÁj™r§úVS‡™ýè×8tl®-ÇÔ©\–5\¯KF ÅPøÃ‘´…4ˆðAðõMÚ7=¾G6ç²}S›é±[ÛC]IT"2VÕ´V.^ÂÛ¡ü¿ù•á9™¼ xW_õ´-]†õ`˜´ Œå=¾ÚʯÒ1AD3½M®&Ä«^?ûö¨¶-¿~){ü˜å?µg>åcAM]ä½þQÕ?³a|ï&Ç_5¸þjzh­–g4D¾\­%¤&ÃJ=^Dt[)þÀ¸Š‹ºN´–´Ù>§•E˜T mÜM–ø$m÷}¾¹'Ý…”{ªÈMË0£†Ÿû}C4C$Më'{@Í–LÔÈ B¥N5S7ø‹ÔRÛØ*ñ³³™9?¬ÅÖùzi…Zr«¸ï. ä8$xªîî7ä{ƒõHöH=æ5=ÛŠsè]¯Îvê›Ã Ï)ö~ÍYÓN8?S 7 ù-§) Ê©b ?øñ‘I#C›¥¼Ïûâ>u…ú”"ÎóžÐ‰¦ì*‹m…9¹ô–å[OQä¾Eæ >Ow›mûXêÖ3z`¨ø±ÐŒû%Á}Œ†]Òn‚·âök•ó«;1¯ú÷òŒÎE»qò*Ë-ï» IuûF½%JçzÁ{¡rAÕë”çdEìÚ«gJ. Ò–ë`^]ÔÒe|lšw3`(ö=y'¬ÅêÇ!Õ£á°Íg'ç8¦‰¶ò •Ы¹ôÍ|[qM…¦`Å e•°ö#Á&þÈ"¿VÆUÀp[Ý&ö(DÏ$•_éaˆ§’1vy”$–£Ïÿê³ç endstream endobj 92 0 obj << /Length1 1379 /Length2 5903 /Length3 0 /Length 6850 /Filter /FlateDecode >> stream xÚxTSÛº5"½wÒkÒ¥÷Þ›H !@H„R¥IoÒ¤)ÒQª€té Ò¤+"è‹Ͻ÷Üÿ㽑1’½¾o~m­9÷Þ#ÜF¦ÂÊN(G¨ ‰‰eªú¦Ö ň¹¹Íàôo;1·Ô G!eÿ¡ê c°650 ÔG!:^H’”IÉ1 Pæo ÊS ö†;ôE:($MÌ­Šòðó„;»`°uþ¾ðAø )¡ßáew¨'FôÁ¨;¶"Œ˜¢ p(Æï)øî¸`0²¢¢>>>"`w´ÊÓY_àǸL h¨§7Ô ðkd€Øúg4bn€™ ý—ÃÃø€=¡¬‡@‘hlˆÒ ê ÀV˜jë = È¿Àz„6ý+ÝŸè_‰àÈßÁ`åîFúÁ‘Îjè‰`|1B0ÒéŒ@£°ñ`o0vÄ~·h(ÀØ ÿ̇†xÂ=0h4ñkFÑ_i°Û¬ŽtRE¹»C‘4ñ¯þÔàžPvßýDÿ®åƒ ø{ƒ#`¿Æpòò5GÂï{AµÕþ`°&âÛœ¡€PFRR€Þ@}!.¢¿ ˜ùy@;›±3x <0ìÐ 8 Šý!@ƒ½¡Œ§4(à?ÿ\ƒ@'8p„:ÑÄÿÎŽ5Ca­±çï ÷رô€¿>ÿº²Å2Ì …DøýþûˆE­Ôt,5TÿŒü/§Š Ê ,&–‘@ $@JJôÏþ#V Cdþj»O·ìý‡|Âøg.–¹Pß¿‰~(„`¿@ÿgºÿùÿ±üW–ÿ•èÿÝ‘†ñÛÏ÷àÿñƒÝá¿?,s½0X裰Z@þ7Ôú—tõ¡Np/÷ÿöjcÀX5(#±ŒÝÞþËGkÀ}¡NFp Äå/Öüe7ÿ¥7 5B¡á¿î0Ø( ð¿|X‘Aܰw4–š¿]P¬†þYW A9ý›˜„$ìé ö#Æž5v%aUéõýMf€¨…Á†°3`(Oâ_ JDÁž¿¬ÄÿÈ ñòôÄÊì7°eÿ^ÿÖ4ê …/Ì¢ r®Ï#:Îë”™}„7G VV»b’¬û£%0æ{ïUnèr†VG½]åP¸pèÛñ+g(›ŠÉy\êqÌ:åçdcVr|ÞTËÙˇR=â[Ï>_u¡·îÊìÜ¥§̘xåü®=ÜGÖ\«˜aë{ Tž6™^fÚæãW¸à g*qŒßüÖm²†ß¿;ÐÿXü¨H··V²&’š‘Æ_‡#$e‘69Wç‡GEâTµ"=‰“±Ä=’gÏAjùûtÑ@{ò ¸W“³jèMÃoš½P³òù=ËG,ö9fßDIZRb\„ês©p×:áœg~®GôâÓ±º–~êO£ÊÊϬõp›ã„‹Û}œ`8wˆÏN‰Ù¦Ë#¤?³Z˜~+A´õ핲ãÈÊ"ëÄ™7EVFê‡zWbëöb­7kZ+PZéÄ zß)Fš¡]Þî/ÆÀvéùé…¥;«I¶zÚQéAVkâ4îÉwž´õL»ÆOº{Áz”¸&. glùŽ_Jkƃ£¤ªç¶€Ò’¥>¢oØ *\6Ϋ¿wÀÞt†Pd,Gs~ª± 6©þh[é¹Añ^¡[i84•À¡}3îùôóï[ _M(Øc¦-岺ß|ÉôRâ»U‰xSF=}ÓüIn@àúׯÆA`ñMr^z×±´/~53añ&EËR¹¼§fM®cÑbyâ©jÛ0M¸ªáñ’w[þ~ŠbOC»\Zn½üÈ;¡ˆõ²ª®{œUßšÓ³é'M®{›¨¦Ï—à竹3’M+Ù åÒä’wºQÑÅ;Â[ÊÚçFv¸• Y> ÙÔ¥NÚCZþn|3ñpßïIl±C¡û¦ÃæFÚ °Ý±ŠQ4ÓC’O£Öµ…¢ûÞ¯Çm [¿Ï³µèq*íei…G¦RÝY6âMÐy:²ì<#4ÀÕÈéb^¦¯xÒ°§¸šê!0!åM6G/¿dB­k’§*¤HØŠ§Ç˜m6HÃÚ"L~Æ¥Qá­†ü¤Õ@©éSÜdoDh’_¤˜ø?¥>>†íDMØQª¹¼;¹³Q•µ¦’>²;tñr`!-ãU=ö[^«³|6ýLÉÂ&Zd’ºÏÎøñšnôåm7CyúƒUJ³æ€”òw¡÷F(õGËôÝpßf IÝdzYä Ø?»x16¿=}Õf7Çõ‚'nóøÈ–R‘ž¸ñÝÊñJ4imÍŽ?›Ãl³/LzŒ»Zýia¢a•.´Ó”³P.q;ýÒËÇ4†XYâ(KREžr©È¹”e¶NT“•X?ÞÁùpò¬‚ÚV”`T88( zr`H©`:CðK6œìÚU<æZZoœþ0PIjP†óÙ…ý­rç0€Ó:·jPL¶±Ym±¸16Þ ®È¶=ÙVœ"Á=8rÄ"R3]($“F{÷Ø—˜ì¼iI2Øáp{œÝx•Ä|Öê)yÖñJ®¤ánÆv÷À†÷<›Œ‰e]“VŠŸ‡“ÚÐÜ: Õ•ñ”;!{ha[ý>ÇÑ_SU‘“;,ú¾Ä‡c»>cT2~¤ÄÄh›ëã‹VÙŸoù‡:ÔoÍo—8ñV÷nv3 ·6“¼ÃeîpIŠZèfŽ›GOâ>ò°öî%S_‘™ôøË“…xÈÈqÓ8Šf·:6GO«äm›î»“ãæ|þ̯„÷óç– Ö~éý£í%9׈©íõßÄ]9+5©,®˜yOrÇë'N+0¦åCÅäNŠïë­hñ©ù­Ãö¹X6Y¿<И¿³­Ô±ãÖ°ÔK¸brÀ·83n'6ÏMÄU¾¼Úwhlj#ßAº‡£¦_ïWÜf4Þl£­‰(ôË£LM\ôf§ú,ø ©¸€­/M½ ’ðöù^ŠþÀÞœhÍ)+Ýfþ!Þ¥4;rÁHµqÇÛàÓ§¦dIé>é'‚|Û&P¡2}Ò˸4ÁÀ­:¾V‹™/+±šåÕ©0]³%ÿ²gýüwMÎÞÊÛ#‘Vú€R¾n†ÞôúÈÏŒþ¢ïšü§ôzïF¶Æ¨]c¸-Lþm¨~àÑËt×ô¢åXyp5ªš(ºáõ*ã|‹òFZë«N ¢«~LëªÐÇ,Ô=¦_ÄúÐ(F ñ Z‘X +íÂñq[Œb`;×ñK•'Â9ã'z?‡qYç„6VõZ(»©¨bü·¤ú»Kœ~ºú™eLJö6Y¸~|¼Êx¿ì³ê0còqòçù—mÙ×dü¯·ošE«.‹öa´%÷gF^/C± <–‰ðŸÑ~Tˆr­5?Ð=¥öu-l¹!D0z.誛}þ…¤W;¡¦÷Ùø.žxèY³‘0uÒqÔÉ{gºs…*¼='‹+ P—¸õØ)êK1*!#ÀVµRëžÆ gމh§¨6œéë®±o… ¾‡Œ–ŒÖ Ž¤ûu}ŒßÇ{ä €ì¨ÉÂDfc£óÆzöêIô,bœ¼þyyîNJƒ‘ÚrÓì‹p–:$µWØ?3~g fÚðxyÚŸÀ6LHˆNÁ•ð± OÄc™}Æÿå#K‘YáNé©H· È­ªêM¬ëûàª""f$П¾Róë*ûý˜‰{à Kãnÿˆiç­óVÅLE=âm?`_×Süé[1ý6©·ŠYÃÕn©¿ Kñð¨Õ¨*ÿZ¿œéýÙÓpÚi )…¼YL9…“ ¨eÞ·’ýÚµ¥0Ø‘-+0º¬Ç çí•Iá§¸Ê ²ж£nðO,*§8÷Öé ì†Zéöà.Y4óú/Ü=~£ÌºÈùétüfÃŒYGeoVÒ’ÞØ ™ÎÞç£;5xù•Mé¡,úNÞ»±Ž/4ËæQ98·¾IXDìÁ&Ícwï…]NÊÿŒËƾÏôHõl£³e¾”±%ml¦ ³ :{(‡Õ ½’t­“ T “Êù:C’ò9£¶éñ< E°ÈލF93óPë°(c’»Ú‹+ÂÉâ%qabì&3 yݘu÷8ú¤…jTª«_Ëýi¸«<,^¶fL»Ó­Âfqò€ëPF½¨.ÉUžø‘­" j;/Àçz­=¹„øY‰Æ'çéî†Ûy*YÛ9ûÊåUT«÷Ÿ޳¯¼\ž¼ÝDËUœ4ñ ôÌÆðöFõ±Ð¬iäÉzÇu–'žÅe6Éï_y;| éhªÿOÒì{¦Éõ³€9¢dw\$¨°uìæ›´åôïÆ»4F³Ò uõÙÉaò 5¯`ôרF:+ED·|úbL¤Ûø”eû“BZ:•z x´Ý翪`ÅñÚ=úeXi AGfù“sÊBUkûò ]`\Í¢ᢵXÝraÂäžú»q¹¹qÙÞÞ«¥Å?„ÀZ /j)ÚUñ-3”ŽFŽ¿‹ç>ö`G×>I5þ˜ƒï¸ZN+êq|­éø ‹Yêý.Ii|û3Ê”)ÝÈ=jã·„?‹ÜuxüåîÌt焺­ÛÀ¥ÞŒÓ5îå>ýÂ+@wuß*Äìòs‡y&ÎíH”H±BÌ‘?dvÒZ{¾ºVtîw‹o½Ö{1 ’™¢Œ£Ã˜-Wȃ^ñm=m©T VÏx>ú¬¾òÙ3¹èl¨Ëoü”ë‚ë¹< Ó‡°¹\Å]'%q?…­x%SÙî Ë ·€~K/SÖNI¾œªÓÓÕÌëCžŒu ׫ J&ŠîhÈC4+&ý@“÷lMõ^F›?~ ÿ)Á\{ölÊ"þú¾Ö‹œ’¦›úúmÄM ¤÷¼yšk‡ÏTW6Å pšõî¢|ÌŒ¼’éÐmãuçFù…ój* Í=®×øj~nÄÙ®;)XÕ1eÝ•¢VVñ¥ŸÁ˜™³õåœÝe^QñYk 'Å!ž}ý$ç0C»õQy‚HK¶ñÙ“Uk-VGPjÓZ»Ö`@‹Oø ‰õd6#™ñ.ò·Zj GLŠG„~“[iŒ–¹5äÛÃzT¢NN 5uç\4Ú´àkÛïF‡¨šÑù/OÁnlݸ3‘wzÍá6ö©¬šÕáí¸Z}Ïådrƒ€<Œp1ø^y嚘¬|ŒòÒ‘Ï ¦Øm<ò^Ýí> Ö]² ÈÕŸ^WœKŒ¯Ð?²ý&kÉ(GCéÍžô"óºÕšÜõö”1eVÔ‰"F«ÚrŠfÅÑ‘›/Ðtûx§æ¶ÏÂSä'­bܼJ‘h|â¢Qð“¯XuTÅëz`GÚ‰égVö¬/Dð6Ÿ÷—¦__»wr6_0Ģл^h”Ê#…ÁãžziúËé:ß^<žŒg“{áÅÏ¹Ó wñÎ4=£Ç»säðò«êƒÅnðvÑ NIs‘: Âî‰à;]ãé #çðtÕ¤ü^èôÎòA¸/JÇvu®’ãÏ¥¤á{‘ Gù!˜½‘` ÊÃ"‹µ‘ŠÁjÊ’Õ5//Y¥bÌÑaÙÏf+ü¶6‡ûR Í âT%.5=×Ì ú($Þp%F=Žã ¬KlêŽ%zþ^³rc^:ÿñ.ia-¾÷æ Ÿ+=¦,|}@úe¼ùå Çv̶ß÷%ÃCÃùd¦hw2‘¸§ 5‡7Llºè'2Qw\o}$úÁ¶Õת¡ž'{)ÄN~øðž~pd–OvšX¯xú0rúnÖm6Ýhç(üŠþí➊-rj¥¸\³ê4À /ø”“{@7ÐÁX7èCÑëõ#/µÈÜÔ² cž«>i‘«Ù²ö-G&oˆ`°z· "ÉDi4BæÄªÕHaé|rC[cKV±“6ŸD`jn8 sSu·)ùPe(¥êfyáVRTщ;bUËþük)].9mÏó²çsKÒz('×%ô™8E”IÖ-f¦/“^«t'ZAu©úCƒ ¢,§8é€~Û£8÷Ö<Ñ(Æ›_(òÛçhKœ˜¼YãFXgœþ`÷AyPŸìdqd©÷åIi(¢Æû\ÈeÖŽj8s^9§ªÄæÅõ/}J8‘S±3N4¬HÿÖ- rS¼!Ü ÙŽÇõbE{€l÷g½!ô‡Ã[böL®—+aAÂ2´Æ¢}%›ú Ð|ÅùWƒC»SuMר(ö]6ðlcK»o\í´ïVÙïŠÝ™<ÍħØÇ°ôTÖÙŒçÖG3êþ¨0T*æÖOÖ[Þ!Å”6Í{„GÎÜcju\Ÿì=ҷРJütÓÞ³”Q€eU¼PLœ÷5Ÿˆc¢š«~¶ºVF–ör–5~<ù”4K\08dC;­ëR€›`MEÛÀ?’r£]ù‘z‹;˜P+åŽPµïXà ºí{P¢•GC—r}#jþúèKÙÍÖ»’ qÜ…–']L…-ïR%’áé0ð¾¨;–/ßxçc°™×FTÊÆpJ¬mDøôÚOĨc9t—Åc&F8í6'¿9ßÿ!¬‡©ðÉypÊÿ†AæDrÜ4Ñ3ª#{¡ë±7 ¿}Ùs &*óHÉ hY)×–¤WÍнRÅõ©Ës§!¬z7lú–ë™ñw¶IU½“¢ãä:ßLŸºJYj´,ç\ç!}À±¡žª0Ø,ç€OÞOâýûœ}±ÖÌæ2K`û9 ŠË©ùØœÉ5~¥Š Â/öãí;#ëådœLçu×Ïžæ¹™gjåSGÁ­W†‘¶óˆZß¼’>Gë’VÏU)ºÕtÙ _EÁrøœ•|la¥Y#=6»Áöâ@ßvØìȕŽ«o ®æxOÕ²4‹]ó&!ö¿Ø4kY¾.¼§q¼ušsÍ&ÇßowýÕÈnŒ‡g¹›>É %¥(ÏË'â陈ÞáŒéÙÇ>nÖÐþmQ“Áóå…—•œ bM^Ä™êЉsÁ¾…:tÙÝ#^&"šúÖ²¯™¶£Ÿ3Ö™"¨ \ûOIŒLþ„ÞŒ8Ë!k¸E¨uýïÐÆFl]®ŸÑ©ï ­C-Ħ(åõéQÔü4¡:A‹ŲSLæ b“- C è¹×©œäÝÆ–mO ¯¾N&ß0ôÿÞ&i9v…¤UYó\®¼›Ÿ§NÜߕߓ¢J³fÈj<=}¸+¤,Ö^шMÍU¼|›µJj F‹4l=7kkLÊ$ýmV”7c›búÀ¹í¾`«v¾öijòÈÛé½/¦oƒÏEHm9/‡¦Ç¾¼gÛ›xÔï õj¦ƒà΂¥" ßI.¤êK3O>Îë*å<í^7Êúó¤Ÿoã§ðþ‰î¾øÒiá·“j¼:¿¼™$ç¦T×ï~ÛIYD ^äe€~¬£:Ê;—¯Üt“LXíqµÂS»:ý6@ û\¿$÷ÍÉ1´§ð\øÊ{‡`Ôa1Ýz¤ºz©©ˆá NßÂïå§Ä…ãÁ îµ…×Õø€IŸ¾£]w¹ëÞ5B|R¡IãaJq™4TC-âvtàœ4HpX¥ßò„¸.Z" V‡}óKØîÝð¼!¯^PüÃ0Œž$‚6·B6!Í;ÞèÌùE«¿¨ƒD mi ûÅk×ÕòòÿlE® endstream endobj 94 0 obj << /Length1 1540 /Length2 8936 /Length3 0 /Length 9961 /Filter /FlateDecode >> stream xÚ´4œ]6¬÷^¢Ç½÷.z'у f0£·DïQ‚DkÞ#z'B"ˆÞû'O{Ÿ÷ýÿµ¾oÍZ÷œk_{ï³÷9×>Ì ÚzOem`V`%ñ”—›G ¯¡¯ÊËàááçæááÃafÖ‡ ÁÛq˜ Á®p *ö/yW0ñ`S!5`PÀ37G/?€WHŒWXŒ‡ÀÇÃ#ú·#ÌU  r‡Ø4¸Ï`P0‡Yæìå ±³G<ìó÷ÀfÍàæú# ëv…Xƒ  Âìô°£5È ³†€^ÿ•‚MÂp=<<¸ANpn˜«;À‚°è‚á`Ww° àwËMø¯Ö¸q˜úöøŸ„Ìár Žk0þâµ»v詪´œÁÐ?Õÿtàüu8^nÞÒýý;úG0ÈÚæä ‚zA v[ˆ# ¥¤ÎðDp@P›ßŽ G8ì!ä‚8‚¬þ(P’Õ€:ü«?¸µ+Äç†C÷üæá˜¡6ò0''0Çù]ŸÄlýpî^À¿.× ó€úül!PÛßmظ9  7°ªÂ_>&œÿØìÀ€ Ÿì{ZÛo ïå þƒäým~èÁÏÇæ °}hì±?üáøÀAî`ÂÕ ìçóoâ¿//ÀbXí Pœÿd0ƒmÿÄ÷ï ñ¼ày/€ç÷كÂl`PG¯ÿ¸ÿqÅ@}]m]cοZþ‡”“ƒy|žò žò òxyù ¿ÿΣ ‚üUÇ¿bU¡¶0€èŸå>œÓß%»ÿ¥¶¿„ðß¹4aÊØþ#tSAë‡ïÿ³ÜÿùÿSùï,ÿW¡ÿoEJnŽŽðl:üxÄÑë/åº!¦@ö0 Ðÿu5ÿ9º`ˆ›Óÿ²ªÐÃ4ÈBíý”W€›GàO;®ñÛhCÖöªæO»Áïys„@ÁÚ08ä÷ óÅÃó?ÜÃY;<¼"ðiþAfè¿÷U„ZÃl~Ÿ äê òÂy¸ë$ðá}˜J°çb¹¡0ÄCà¡G?€-Ìç÷Å €ò¿M"QPñ$üÀiüƒD8ëïƒ(àÿÀdkû/V„ü‹} aÿ@~ÐÙÑ þ/^týÿ‚" ûð¿Z·vsu}xþÐèùüÿxtÀ`O°5ÎÂ,ÌZ<øeMpëE•,ÇÓï£|øýG‘'XFŠTî›:ò—Çü¹Qó²Ó?¢.WIvøŠîŒñ8˜¯ø¦F‰=Z¨kE·µZçò'‘¼Ú«»ñýPëèxnɵ±{´ß¤ûÉãDfŠ‚ËåðûLú–²KSÅy¹ý>&kÃ/n<”ј(LJ~<”à6Ùô¶ ¹jÙ©évU&ø‘Ìèn"ÒÖejߟà·þ/%\ȵTším|gµ“ôm©w?»…¨Õ,ÇSÌÝŠ”×ql'­Á¯Ù¬àÃzÒOÄ3T7ÆTŽ6bTuíšTVQûRPåWãV±e?xZ±~3çèP(ú¹¤ŸïÍ/ÈZÒ]ZªL*©„Û;­4ñ+¸†û±š¯zõàD‚¹><)c*5Ÿkè=iƒ¶Þ±Ïï„5öPTk,„K®n=@7)3ó圣Årà¢Ú ¯µ‡P—™0òðúñΓ@ÃáµCBÝþû+Ò‘Ïô:jJzkÝO™ÞÖž@j™k´¢qrÒè?.èÄKï -ÿÄâC:*-ã*qËC.µô#©qóÏ­iEúö¸|=7Yô´ã{Oõ“ É"L[n+’£©O¥ëÔ-øÊ§ðwŠm¼ÎžfT£Ï¥!ùrõ¡$RM5Õ¬åhÿy “µ¸ËJ&Þ«,@ADFBÅóœitkÆØšÃ(³£v·­À¶7¾3§ÎçîÑ L ¢øøcj¤zoªôãvè¯&¾,H’~EÑ{M·–†aŽ3£n_^Qp­ŠxäGDžÀ\'cißä’Õn¸ Ô==ø¥é%x%ª±¶>¾ùSÞ–(RÇ“ÑZ":ñËŠ¿¦}y$3Ͼå—0…ò﫜a±.{‡_ xâñÀÃ3ãú¬¢t ¤HxÏmª üû݆Q©?9™Øg|¹ßêžïÅZÎ+¿(%÷›§Õ…³4 Sº0cqHÎ5œ0'Þ~ ÄòNÈ}Ư$˼#ç;I¿z ã.!Ù±m@á¡lzfv]æÏVË" /‹³‚„0èöÉß×»` )ê<•§Ç'«5Nß+¼.?ª7- ”Ôå§$¿²‘b0YÝmÑשÁMÎØÔ®U c-wsÞÉm.¡W^Q±©î.Ѫž:gÈž’Ús4z¸ŒÐ«z~ÓYæU8ñÍ*³|A8pÚJ0[èÛªïÌ7¸Ý¢X{‹Jï›×MyÝT³‰—eóU/ínŸ ?¿ð.§è3#:}=²íZ^È¢“4Çó¢ýý„¬†Y¦íŒñéO³ÇQæ‹ÔP©«ý×9KÌŸ›nÙ&:õ¥ã©‚RG¸ÉðA¼êhÜu ÃPhÈW•òÒ»­ó'ò1O-í$©)0+l—Ùqôk•C®Ã(ÀïUÝÉ‚`ÒJ4v¸S‚©]pÑ’ø7u ¯NÆ•M\{™f³ö?«otö]µ‰$Ú‹í¼¤ƒ`§+|·¦ q å¾ØsÜ­ì&ôuô%&ŽÇ+®–^,¥‰³¦²ñi›I`¯Aϧª§/pM{åoæ_­Šå&­E§³ú>‚z…Ï "ƒ×‡ ßÒƒ‰¯#ÆFjø¿¤ääÐ&]ôòä&Aé?¿r/—zÃÁ`ÀÇ@¾qnàäCö_Ýëpd&Þœ6¾úŒ¯~{ÒËŒ›÷k‰œÍʳ¹‰dZ´M¢Ñ†£}óÚ®s¥¿ÿ§§Sà¶ë[þÙG5Åd„±›.ª:}ú,ÑNàPQ~ŸÜ´òw´Øam'¢Œ^û°ãÆ]Ç‹r+ÑÏM_/5u‹]ƒ[°˜yÔ¨W÷¸×[cY‰ôêç¤ÊûDri“»íŠâ¢13â´÷¿ç%éÿH|b¨f@¬ºèÝ\ôaaÃör­¾ù©ƒµ8U â¡ÌÂ÷Ù*ŸJAÂø áé¸ÊèyªûôTà®”qŠ@è%Mß4Ë#Â̽݀ÿhÐ%»¹;ì°ú<Áê1ßeÀA³“ÊË^?—Û–R m¾G¾Ë ‘_ùƒþáCÃ5Úkg°Ë‹Í0¢_´ß$%¿“Ç`§æ»¿ŸŽ;Ž!:.\Y¹0|Ñl1E°Û5Á¾uÆtú¼võ9Pìþ¶‰w:†Èª_¡@ô–ÂoHÉ2 u¶£œçÜz³qš£»Ô©zî\çÑ“öt'ÖêÙ¸݃O ‘÷ø:Ï …b×òR¥`ˆA¾ÃÜG­ÏƘî:4tÄ´ÇZ‡;M÷:G= ÎZ€Çî2/›$GïW-Ô“dBóÏK’Å%ñé–ý›É;.ïw—}ÞQã1è˜? *™y’ò²ªjCÝÆnoN@º®¼E+ë®77U¤2òal¸æøˆ†µ{]sž‚Ш5ɾÏL¡\í5ãÌJáù¾‚íÃꊤoTB±ÎêºØÍa"[ö‹Èÿ"eâ¸ûã—©ŸJµqíh×”µ’³„ÇgqfH³º’¼·éñô÷¹˜ ‹'D‰_Žì->_©?ysODw@*ø­}¥±<3¤ã2\±»:©ì`=z¶¶ç“—í[¨ûñåV™÷'E¿™»¼¬ýO¦~B6Ál/Q)‘YØ6!ïÐEAUɧˆˆl½ÏZŸðdÝ¥¥£RÞf­´Ì ¬7Ç:À%Ý­¾Žå"£ˆ úÖ|ê1m³`ö9˜,ª•bañ¦UÅ$O?­"0º2lÓ»‚ÈÆìær.#M%0}RðKÀk=U>½ù™–´U÷%ìpˆ¢2Ì-ÏK·–TÝH6hö„÷_Ù«µÖrÂ[²¼³øà‡}èEw Ûœ][ííߍd¡ÎWúÀÙ…&ãûØéÁüåìEýX.ý qRÜ»óâiª{U%ÞŸZ§ Wm{ƒgαP—¬%½NA—*–3–LÉg½ÄW„8cQ«$* Êæé@V–ѽÑíÄç›ÍQ7ZA«>TLJÑÍoƒ¨1u,Ó•~_Ÿdp`-áÌ _…Jn†}¯êåóùÒ_M=êdðMùEãðiU_CBFo"08¦¢ÍA[Ä–ª´YJºôçqyÈ0à»>ß+5`ýÚf‡Z‡)¾Ô ] SÊôÂ`äÜünµºž&¾`·’äWöˆ~†'s"È`ßÁù‘Äi»ê$ ÍŠY”&ÒÓ%1ê좌BôôÄESÙ›ŽXt  ŠÏuË8k†ÁâY_G½w(NûÉõþ»¶gásóÕf;§®Ÿ=êC…ÙgkÖYR *ªåÔB8­EeµÅõ¶É0lIå€Ye Ë6"Ñ,À‚1d yV0ŽSTq|’„O¿s¸éÓùºƒX­æ¡µ3¤SøG“Hv—’a2«µ|êýæ¨í3…Pó‘U2þ΃ÒwßÎ $¼=wl¾ßè7†e³yÞÂ]š/›¶lÖb/X—­1æ|Ãf3çZSG¶ÁZ]sÉí’ÒJë« ïç…qtïò‘ÌýW¯î0÷Z¯Á::êÂ;û¤ -GrçE¤l³ñ|Âø„Ùö •ž_ײÌ[¿šÑÖÄ]ÒÆŠkUî°_©=ŽSY£ý1;º°ŸE.c*oT‰ —|uÝ_WjB¦"„ü•@ ú› 9²].ÏÑ*¿lpAÏib[s³w©J|77ú¿‘Ÿõ¨>2&š3ðo+?µèB×Ýgýdy„²¤Xæ¦ÒŸ£²¯Þ?fsþ ß–÷À>î¹|´äÜ‚=‡uSb )ûñ{3õŒ}‰ªNSÔ¿úªé}O™j>òIÝ$ÜŽIjÉ“(PvçB.Ä[¯²½”âu„n …ý¼7KY:à u¢L}`ï~sîÃQÛ©ò5qÆþb‰³ ”Ë+ ›V`öѼù³XŸ§æûú Š­ 5cß“+¬XT7„[ÃÍ< U8¬´¦n}8ÿçÜ7©–þ/¡¤\J_¡Ç^f¶*·æâš^* èÀå'ŒìgîMûÜÅC¯Š;ÆÞC<"<3ßRÑùlãyÉŸ,ãÉ[ùF·S–ã5¶¤ŠW¯' “:t%¾ÍÛȸWÛÑã=j{·ñ $Zï½lÔ Ïz;f£P…Že¬rE’nj³˜‘ð²=€ßs‰zËê@j'PÓ*¼ªtÒ%3]Vt†kù JÛɘ, n$qROt‹Þ~kškL䬫Es‘!¸‰¨Ä 9«â"pI–ìN\BQ؉hÞД+qÃ:ê\÷BŽ{›9—5*|˘›Ì-Ý=œ0Q9 \r\zá¸Ì’¾IFM¡ëÿÆÈCŽ!÷$áüjÖ/©*èab¦âNºTÓ&nÀ8ðŽþ$h5Z“вk ¤ù@àè}èØ2Ç2F賓ÏóŒ_Bo`œêÌ#Ë’·U€L––Z÷Á b7¿RxU`g—η*¥JiÝve'P:zÇÅd•ú{¦´ž×ÍŽU縭…zÜ#bó<ÂPƒ¥§BàÅ­…未jû“ F¶Tý{N²šÃ­¯Ô×NÖ›QoŸÏ˜L¨/jä{=+ÓId§íÔFFåCb’0hµg•ÇÖz\…6NE¾G_ûHúc"T¬3þ0`?Ï!ÉŽúêòx'=¼Ç^Nh¿ÖüeóÖZÏè))+éÀÕ²­ÞדoZÏŠÎóÎjï6c\S¦§P#ÄBD;4ßñI‡Qê§¢íq]é˜lb«6_o×Ê)n¡?kgqm}n…ýès•–^¿ø´¿‹’¨õ§'¥ÖÖ)TgSÛmÔò¬xú“‡:ˆ£Ò¾Ú÷=Ÿ;¨Ñ "{V8â˜V.ÁUz³@µî#.Ï vTµ6vs¥Ï‡ å̦²|ËQtJ9†R¡Åpë*¯ßȆ‚kJ‚‘úò¶øRè|qÔÄSª1‹'øR¨žqu× —ä9±xø¸#²§©Óâ•çó‘~V÷ëüøí9@¾Å7ápvvsÒ¢%´3ÈYqòרt^rݾùSÛe_rÅí›ø¦Ÿôvô5ŽÀ®>c]TÎq_U[«`ŸlûQ<Åìð@3Á P®÷¾"f+峸(Zåf 94óŸO7 ¦Ø½­üÊaY'}³‡™‘¯)+Ü’ytÌ®>£¨ð…¨{irŸZOo FвŠÀ.1MÃÔ—.\Ÿ\¿‚šè;íë¤:k@”JËÔjÛ*Qž¥ a/qƒv“ÙäæW¬ºN±h‡ßc({R/¼dÞmš0ÙíëÞW3ºMà=zó5y3hâ€iÏâ <ºôèÑ á>µÖC ð½K ôãÃCªt3°x3l]ÔÛSNõ„™S¥ëX¼Ll{_ÞI%•ª¡ž_¡¥,‡¦Û)ñž`Œí}ZÁ§÷K5ÕkJó ¤Ìb)•©m¥vëÞ/š äò_gQ ô[ðĉƒõà†$Êšp”±Êç$"²Boߪ=×°§IvR–-õú¶äÈ}Ëg¯ÙÑ21C2Ç"Aräûû¢‡1EæÛw G^Q⋆K, r@~fÊ©fÀIY`rÖùzÎh¹øç¥È‘µ ìcÐyä U_Y’ÌiYÁ~±Âªþw qºvË“Ã*EÞµÕ-– è=‹U S%Ø6,ÈYóË$ÿކX´ ¦P¦÷Œ@{,×d‰è>fèš’_bK løZÝô»­D]¸Xà8Y¡:Vr\ëç3µ=•ABfD-ü5Vvæîús žæ&^©¯Yá`ëÒµÝaƒ¥:÷®Bj‚œÏZ4ÙaoCrl^džohÖqœÃÞ†,o5 'ÙÆxarhÂw©½ýI¾ÂÁ¤Ù>ÞYÞ8Åž¿‘Z(³û鶪…ÎZm‘eÜ>.•sðNh´j#‡éTñ¼½ê¥Ì¤³¼{$¬OÔ¾´­#M1%XPÿìá;U¿[fÆHÈŽ¥1ï¸T—0sUP`_cü\ÒÞñÀ§úÀÙÆØn|[@éäŠLAFãv¥s–¡¯ü¦/Rf‡vå¶ùRM=¬v$©"á­~øÝ›ŠðWvg€\ŸT‘…… áGAã÷e_KîúW)­Øa ;,LÕ¯:Šñ^âé6º|-K‹2¶­ôå_Æ)uùà¼ÒjìÉM‹£õeDwæ…ª„9–Ô“$ý¬cP<öè³á®ÐÆêwAÍ—¯og*XYP7& |€¿ A³é¿€žÄÐOÆbí;. &wt6Q¨¸[“,”wé‘)bZ°)¾Òw¥¸ÓßwEóŸ¡USVy€ˆÖ)ÃÄw­4ÅÑ8Ç>†¯Ä„søÔWÙº~žY…OŒñ ›ÜÕƒ[VYp@ïùÕ–ýóÕ_|y\ƒÚ+¾žò“ØB û%N#°N€XezpCͰžª‡¦zU­jN 8j‘L¡ñýu¸U³ Ãs™"ß;`8mŽ›Zû#ñÌd-;«¶£6œQ¢æÌÇ•ž2fÔÄ”Öà˜E^3ÖmgÚ-bpâPyAýí ÖáM¿íö¶Wï JÅIÈ(¹ýÄ}Ñ\_'S³)+ç@v!^XäÕµýÖÁh¤•nQ)dÑ^ÐóµX¬ù.»eeä;N•§jñ¸vÆT‘‹=ÏHÍ¿RMÅkÐâU9¢¥UÂQä*u©–}‡íÔ5p–îÒßÕ×ó}Vº¾cЄC¶"!±o’¹ÞÍf.Û¤fe?…Ü–×xºl7ÚF¢È”¥ùQ¼CÏcW9„„r±{祂‹¿ŠBU+ŒLÃÙèæéZ`à;uç裴x23ƒfx*üR!ß9‰†­v¥­PTc6ÙkÀêIëǧ…”; ÅÆ}H|‹¥ÛQ&z¦s­0”òßÔ}aã#-B’kˆE–ø)¯sSôF­E¿¬¬ý×/žÛò±8ŽúòÊÏ…ˆ`×M×÷sIÆïE™%Ð šÌŸ¦jiø")>”µ ÂÎzŠo›ÖeJò-\ºü…®ô§|CÕŠÙ²óæw°Ùº% ï•9ª¬(s&ÀGÓÆ¨è_µ¾¾‹jÁ Ö”Z^¸àUõº¿åšÝpU»‹c5ÈbEKe«zìÙ“+‰dü¡_œ¼p¨*zì¸ð£i; ~³ò-müÓ8VÞWYÆ»†*üØO§©¦=ñ\ß~¨à+²ûÉ~ñ‘c°4„äÿ¨¥t-ÐÇ'rÅŽo×°ï¾G„àÔß?‰íc©Öªó’ú$‘UK–åtRµngÈã 95½ž÷}å;Í ¦ö~¾4;Èô»Ã' i 75ϋ颮âäþ%3=«kž”Iš#°›ÿ².03ŽƒRïì‰k¼×Z@\w~7®ï:Á³:$O{žø\që£DJY;ãdÙ÷8Aêu ¢²¸†kã½5“­‚)Œ> Lûø¨Œ]ƒO'ʨiŒC3/"'K±‘Z—óSœí/Pì±qfÕCgTñ$T.ô•V Ã^Ž‘”Øv8ØT;á„Ų«êÅ/[®m »†aäFHÅYµ›¦o½VeöV2ê~Æf™}TX^oÉómØÇ›^ÜСÉWÇ!xV.}…‰Qš™K|ç4ËÇÀÍ¢´j `„ Ò¡9siÈ‚M§0?¬¢£Ò#L‡S[(›ØRY{m[‰wÉ o^SÜÙEÇõ.°}Ä1ù!ê‹0× ýª6ö8E·®ì]dI½TTù©BöšÿàXP ¿#½ó}b~Íûg ²Í>’¦F/)­µ§ \s£`LLWðÀÝ9Œ™Nxë%?–þP5 u*§ÒJJz¼y€þ4ó¸þ€‰Nàȯ¬T"œ¡º&œæX÷Û`Ùüà 7°óXn;íD.ÏÀ±vý–ÍI“kõô´H%âÍüõV‹Í ÄšãM-u¬ŽÀà«ëhÚ°é]6djn>9üÝæà=Q®G¨ÖúUØ×3¢ø Àn1ù)eð#½ù7_§1alþãÚî‚ÚHÙlûaÞhÔ ÈdWPǧ?òÞ8ÛL˳Õ|’ÍõõùÖ1j9ñ˜…»Óe‘X+æQk˜ÏÍd¿¾ ÒÞh}[Ë2zÉýì+j¡oø[අU$m¿Çq޾鋼h?Hè?~\5"D›¤iäfà³ß¼=ézïö¡ìÉ»i:2áœç›:zñØknò¢ÚÑ}s.õrÉ!ƒ?6»Ý€Ò¹eƒC¤Ùåmü‰©—[–Áï4šP¢yc=¶å(!>ž;fJèËTÁó ¾Li™¡ÃäçC$wáêÕ¼}¢f™±{?_£ÔP·˜U¶àXé/´Y_ö½?Çó£š.´x†b(œIè;»±ònutêŠÇ¡+p+ÊC(HèÛI zþ'œ|á_)aÙ;ª¸qaÁ\¸>‰±PÐL³çnRŸ3æ8·¼úQl*½ÝI÷f0Œ:ê0.û&šp6`Nb]óLÖ«YE\‹(ÙÑÔ »2jke;Y5JTŒT–Óu%øQÄäîHeÓíçi ´ržcnœZëÊ ‹œæ*2A¹žÎd ‰•"Õ•3¾f5]#îÆÓ(ä±hž4×áz“Ìn!«[ÖG%úe¡Dœm)Úþè¦;‰üíò•ø Æù{W•yø°ïjQüMM‡ï3jÕ´Ù=è1ŽÓ»bŽ[U­”/:y~ ~{îd´Ê¶¦:²H¹`åfÈd8v{ôÔ6‰ÂnGDŠƒ\2UXÚiW½*WEb¨'AÎô‹¢sG–1yÇonƒ1>-öcŸœO"²j"t( ÇÍ仸6 :æWQß`¿ÆLëÕDÍL¦‘¾Æ:µccXîÑõ=ÓüUûkŒ,+`2LNäœSˆ¾húÂåç+†NúÛÌd¤v'L¸nÓ{›F†vT VýÌ}»jöûÓq½ÃsêÂOKóþââ öê§oäoü#÷–Šñ`Í 6ëgRiýׯÏ3~*»%jîÃq…:žuî2¾¢yjZjH¥ãhóí!ñÔ|WÅJ9KÈtþ|¹Iñø!yÚL/òæÎAÝVá,ùíRLI`ľs2V´ø$êª É"HÒg‘X’£Äœ”Cs–\Sm’=/aðptï³~›.Õ,9áSN•äâלÏÔ'gk«au{7üÄ–MŽ™¢ï2%´E|ãgŽ5æíêÑ8D&ËNYÅ1ô¤±ÄŸrµb£Æð}“Ò¥ÁñÁБøøB•í¥â´W‚¬¸†ßcGÕ´íZ’»¯XOÓÑñÕˇBåå´ è2ìð7'ÅH^£Gèç¬?Ê*;¿ÛIÅÂ8J|øJzEM`ö€Œˆ2 )¸jrÒG.CPE)ø0°ïÃ:‘)þ×£7YyD¬NqòKÑŽçÍãÞ6tj´:pôþiÈÖ&¿ò´¬žj4zã¾æÖIÖ¹òs¾ÇÑÚ,…j¸…ÍÓ¼ÞÃÛ¹I™âN1/.À„|÷=9iUBS’Ðý°ÌÞgMNÿÒF€‹ƒRÏ{`(ÙÆ“9`7¼C¤þÔ¨D\ÿ›;‡)<éö®íŸÝÿI]™ endstream endobj 96 0 obj << /Length1 1779 /Length2 11233 /Length3 0 /Length 12354 /Filter /FlateDecode >> stream xÚ·PØ-ŠCp ¼q îžàîÜi ‘nÜ!¸»»K‚'8 nAƒ»Ü#w&÷þ_õ^Q½¶®}ÎÚ§ jre5&3ˆ Pvbbcfåˆ)¨Ë°±XY9˜YYÙ‘©©ÕAN6ÀÿØ‘©?A0ÿob@c§›¸±ÓK  u¶°qظùÙxøYY쬬|ÿ „8ðÄ]@ff€, tD¦ƒØ¹;€,,^úüç#€Î”ÀÆÇÇÃøg:@Äè25Œ,¶/MmjSÐÉý¿JÐ Z:9Ùñ³°¸ºº2Û:2C,„é® 'K€*Ðèà4ü12@ÑØø÷hÌÈÔuKã_5ˆ¹“«±ðb°™ÁŽ/)Î`3 à¥;@MF dÿ,ÿW#àïð1³ýSîïì? À&›šBlíŒÁî °Àd(IÊ3;¹91ŒÁfÛ8B^ò]ŒA6Æ&/R7HЍŒ_&ü{>GS“#³#ÈæYþ(órÌ`31ˆ­-ìäˆü?qÐôåÜÝYþ¾\k0Äìùd›™ÿ1†™³‹dï ”ÿ;æÅ„ü¯Íèàbeeåeçí@7SK–?¨»Ûÿt²ýa~™ÁÛÓb0è 2¾üAöt4vœœÞž¿;þ!³±Ì@¦N Œüoõ3Ðü/ürÿ 7€.ë‹üجüüóIÿEaf°û¿á^1‹Œšº¼¦èÛ¿GþÇ)* qx2qp˜Ø¹Øll¬.V€÷×Q6ý̓õß\°9À÷Ý—súe—¿5@÷÷‚Ðþ»–"äE¹@Ý¿B×cåb5}ùÅöÿ,÷?SþÿTþG•ÿ«Ðÿ—‘¤³ÍŸ~º¿þ?~c[ûß/ÊuvzÙÈË.€ÿ7Tø×ê*Í@ζÿë•q2~Ù°Å‹¢™Ø8™Y9ÿ²ƒ%An@3e“©å_ªùË®ñǾـÀ@eˆ#èæ%‹•õ|/KfjýòŠ8¾HóOðe‡þ»¯ØböDz±sqŒŒÝ‘Y_ÅÎÅðd{ÙJ3 ÛŸb°0ƒ!N/)€—½æä?.–› À"ò‡é/Ä`ûñðX”þA¼µßK¤ñ¿ˆÀbò/zÉ3ýý1‹Ùo Àü ²X̃/],~ƒœË ç YKw;Ë—·é߈è7È `±ú ¾³ù ¾0³ý²½0û­ÔË~²@~ƒ/Ìì~ƒ/T~ƒ/}ƒ/}~ƒ/Çãü|¡áò|¡áú/d¡áö|¡áþ'ü¯›6uvpxyöþ\ÉüÿùÆn@SäùS@«šÀÖ›j"W¦­QvN´¾_áHš›.;*þb‚·çs"ÓÛ·«Ø쟞­µðX­ V¼Ò"øñæëZáÍM6½Æ±…îåÙ·å::tŒ8Àfx'Mª®ï§èñí϶f2÷¤iš*¯+,Oi™QaF£"ßðòr Â¶‰d¶UŠ~™šn—¡rüõ~ô(Drï6­wˆk½o¡”´–F´¿f'w‘¹/œºÛÍM(g4˜¢Þì–xsKçÑèGgâ8¬&ؤªÃ,ŸðѬeßÕgS&ÖßNšƒ÷mäNÊYünÀ¢±Øúhn;}—Ý… Ûä-6­{BÍd¾Žùþy†Å)T™ÜjK„´ÌƃuÇ=F?Æ"é…¦@EîÒŒ¶ÀkÅæåw³Ë6Ó1ü]g"ÏÎ?Om÷è^¥l„íóvÔ¿6ÍÇ»?R㦇 ©’„9ãíÐÍ rç[ uL–|#ÏO÷݉H×åO†ŸiZ„W·aÌݲ/”\Ý Ç²NC,©P›|g™ê—V–œtë·k9º· ð*¿N]ºíP ñgø’ç”í{òâ¹Ù ª}…ª0Œ¸Àöôö.¬RñDÂGìz  ìj~ò€{DS"•rb{~:?…I¥ô^TH„>$ŸÝÉ#ûExœÜèú[*dÕ÷¥¼òe` ‘ÎU¦cNFHµcJ{„²‘r0ù(V»'AþgKld7m¢Ëˆ‰y-,$ïÎÜ`â¿ÊðrJï9ìÂ/že,¹I†1}„‚ŽòÆW{÷d\ײl¼Þ0Ù§U¤Mãæ5€øF¡­Äå¨ÿ ´* ¸6„›#¬Cq®æÀSû¤û){«Š£Ò@*Ò³-« I3âMkTqè­£%…bÆ!\Àà&.™æñ—[ë:2J•Ë`¾ìy3¢ÏÇÙµn«vŸµQe[’d¿âC+aßVÂ7 ]Ñí i(àúˉÏÚ5”àD)# yQšÏo£wÊo~|$¥„ü¢ÇÔÙ¿dî„¢Ò(õ§Ãü¤U(BØ,Å$8-oà`.Zß|·Aé€ r×"œÂëNWÅáýyÉðÕ®`ô5ʯífÕB1"çbZ«ÕwãK2)‡_êÅŒÇãÙ¨s8ãiH‡¨ZÁª,™3dؽøó"U> n¦ÏåK¤§ý§ð¾†%z§Óïz «ãÊÚ‘r}Ûl.Üg%ô¡‰ÙØôã Rp&‚,Ç r¿væ /¥-ªÅ|ݹ‡©£|GH‚ò–ˆÄtã} y:ÌÖ›èYèN…Î:3]Zrjànã°Öc¬æý»LÿGs¾×’@bjªˆWK­X0ãG£þa`þäÓ2ñƒÞÊ| ñ-NhÖ.NÄü"ÎFû¢O#…2¤ýúQu9:º]© …?·elQk<±æ§u‰FÛ>~·±?dî…ºýAa^…+kêül„–Q΋…¼3á—ù<õÆÐÀÆ®¯w9|£_”dkD† ù• &X¨!/® úùôc8—w@ÄôÛ*Ô÷¡\þŒ[º&¸ÐóêÐÝÚnP…e­wª·¨ ¥?IýR C£Þà ^©[%D¾T±*Ñ^œbë*¬Lß— ø^"­SÓ‹0œAìª4P —¶1È…•&–@Ρ¿ß`ÁhúFd¾›8²ú.æx2»¥Ýªëö€_L9~®ˆÔ§Øumå99ÜÁ’ùçæž]Ñ_ކ›¾š|"!Uâì2+‡šWrŠ9_8@"ÔNþþèŸQàPÊš{˜!n¨k=”4Ðj_-Å¡(Î˸<ƒÀ„}WŸÂ¨<™…øÃ櫼õEb÷î+4@¨7B!W…Ìü~ë?\]àOž¹Q`ýÂpÁ·¯}Þ}˜ë»?™R¾ÀwQ­Š²áSågëèJŽá†bÕJ°ˆ•Ý€#ôi€¾NLäÃ:-—® £/•æPã0°&[è=Pdô~ýˆ‹\CÁœ;×§)ÊSê©­ã(\¯ß'”d¹Øà_ŸEPEÙ±4[?t¢øé¢_h”—Àºù—šÁ®Î¨ÿˆVn[+ÜŽ/R´Î9é)æ>*JWž0’è Ø"½Nú3­$5¹ K›¯í ¤fÌIÁàx4‡#ˆ„_f>ǰÈFÞd·ÎçUeÉ›Mßîj5²¯Â3Ò‹ß‚ï.äÖK?‹|øŒ†¿ïçÎZ¾ªCß~:{ßÝ’“(€¢ÑQýcÅF3Ö ¨è³æ˜ƒ¶&4ÿ N|BÕªˆõÕ lÐÅ$´!­?tùœ?Ër—¨!ÃÈ‹š‘H ðï9ÓÂGï1ëO›ýÑÈÚͬpUiÆ~|Åi°/;§e¿èyÙ[ÁÚg¾JQÒïÚ{ClÝØ­ :>¿•ÀYž<ƒêëñ~›ôp‘ Xµ¡¹Hd£âÇfeNbé°&ö1!ÇÉÚ!–wg+~B5’U˜n4å׎ÑyKZXO,Î]]×ó’Áá"{½OÏu÷Ž—iD(ŒÚ£—£rxZkP„ã¿fõ- ª§®>qÐ2ƒ »O­Zœ†ÈW"Üôß| ¿ÄaoAÿ¥±­ù qY³($[’þ:œ¯ÙÃÚ •'nö ŒÆ¢øÖ—vÍ$ÀJ}†§ŠyqG/ªR†UÖRx™>]%`ºZ7NŸâ ìÀ=ê\,:Ú‚B‰X1ÙØFoÒÎâHpâeí ©Æá½ÙÃè¥ß(ºsßÊWëÎÏR8ðFè®",­ž¥¥# Ä[‘09áÆâá §Ö©5gV¯„%ÄŠˆsß®!Œ¶³o„½ý2ç—Œ¥HÇsjfɓ˺¨zcògÎÝyÙg»òço‚f+S£¾¾ÂM%~Å÷óc—ȇ ;œóµA)ì_j-ÓJYäƒ ·>œã{ mżó:SWÂMŸ”жÑÒwH¢yŸhhœ&ŠæÀMe9v“wu8…âP’42ÓÿÜFH€wéÔ‡¦¸# Üäõ 2® ¸€ÄSÁë´î¨|1V1œªKÚôä3$ìàÎä"½AɲyíO›-}º ªekh‹œðúA¤B•ÁˆKô»FùI£C#Ù;QŸ´eÈe¯‹ÌÁüo4 ôgzS¬GÁ2”ÝV{á¢Á¢.~.ó =ã­Î’×RŠLؘÓ6Ãr£¾I :Ç)ï|i©Ûæwy­þ,¯ÍSµ·n&ðþŽ„ @Ž\aþáYØ×¹‘˜’Šèm}aEù Áˆ¶ÈµÏ—U¯Åh _ë?, ÒL¥…‡hú£ôˆGùu>„o]nK³¾íÛ(ºù>×wt,c„æ‡æX! 'жÒ}DfÇ)ª¦½Px¬š,aeà C‚)yx­ ®7:PÛñL!üJZòn£öêÔÚ,¼OtЙaÙc, ì¡„W,fƒÙX’î^Œa‹žUÓ^­ÃðÀԨ𛇜—: ¦ZÏšš“)Æÿ8è¹nл† 1%sovÈ|ÿtA©êªG#ÖŸ±¿nrGf¶vzÌàC_¦¢S Å—P«ß[:· —#ž»šþèç N©ÚWΩù­ð¼cT¸@>Xÿ!`¡÷â¼h y\/¼>~ÔâfgŸŠ=-—jîÆv¿Å9ƾÿ¤² ögˆ½Y@sïNÚW¥èÙQ/VçNhæH™¬ñ=ÞdÇÊ+¡M]Ú s´ÏªÞYÛú7Á‚0Šëm¹x1ã~3³ô”G¬öC§-aRì´VÁ€@ ‹…Ç6àåÅî+h‘È»*0žqQž0œÌ}Šž*liý÷‚Œ~ÞÛÈ <ô¬•ŠŒ çôÀUNZ§ŽˆN?ÀF •=ˆ"åÞârZ¢R€Pf|u¸!‡®è¹+s­¯7ÌÎ5´fì{Om½…Ãþ§É£ïwNj†88äà-ù’(2©ŠÃóbim³JÚ˜O¼ƒøHï6´¿î-&Áø¤2DîÂ/Þ˜µ¯ùúiá«Ë é ýò,ùÎ!)Y¢¸ûdç'FÏÆp{¨ú¡¤ÙÊ–R+äªV†ÄƒƒF`ÔE‘P= kpdG:‡j?‹çøV€bδc@»A8Ÿ¶J‘Ó1«ßkd¦d¢ðƒ\ßtÐ+ì+îh¨Þ‰›…(Ì ¹ÔÜ$'ª&–©©ý×ýÇò ñÓ&lˆ¾ -ÙWùvR4ÔðǵڮÉ_¶«²½Ð›j9ÊQåuçŸ×F$ÛäÇôA/æªÇ¯@Ø@…ü™õõ×SË:‚üùƒ¤Œ¥ÌyT;jgN§BŸÔ¬$ç Æí$ Ö·=Æ–ü½+E¯!ýçŠMèýpŒhîF¿æ86[€ â4ø·Ü ÑÀ1;,1ÔØ÷¶h(¯oÚfýâ7aœ÷¶*X™^··ªØs´ˆ½£èªrTîu Â9[\æÄ˜Ü]úü(£OKÎÑ.Þ&3Ål×Avg¨‚7ö³6^b2»žÅpPGq§Á,¡X”""sÏóó×5g(YðÉÄI~2ÔW$t·5©óå¡|¡€®Oš<…!јܧb¹$+,Œ°ÔŒXç‹¡ï"&²Ü…çuC.'oœ˜–ïÃÌ«œ/iö¨›6ã´0U ¹Âä—§?“=#âù´‘t†Ø‹æGgBEÎVÔvÒIðûÓÜ!+5|¿|;ŒÛf¾ÿ •ð^ÉôÇ¢Qnþ'š¸>CQ„ B§‡ì¥ Õ'pÓ™I¼ã>=ãÛAÏ] Û?ÚTp±}ØG›UÆoU4oÊåÃs²P4¤aòOáÓ¢‘ä5ºhem¸ø-¿êw¶†‹Ã«6ëNøãóu´.)zžÄ ªøå–à uÓÌA²B¦=²¼K1¿EºnšˆÏPb-ž-a+¦×r5> ͽ¡›@]ôE˜#æ^C|óM² þ<é—ìÃùy³l‚ÿ£$‘ž’@Ò(ë=öÔ h­%ñÀ.'v;h^‹õâ 63¥GN…ÆÉìƒ e|ÿ|èö¼˜åFôë8óH¼Kßžj¿²_i|`?·-£œÓ¼Á°h_êwÃJ#fqgYÞþ¨ó£ƒôäãj)ÚâÆ„3•LʇŠ6ñoÎŽ‚5¯ïUë47lΑˆRLKÜDáÏuÞɃvìÛn•´PŽ‚A:ÚÒ›H{RwLY‡Ä!_Ÿj±V>Üf§o+¼g3ò¨üvNßß÷Fø6Ñüzê:0S_ûŒeÿ:Ðõx®Œ²¿ñdjÉõðÚW º(úf?1n–‘[ÅF‘‹Ý7ÍnC·#Õô„êо4Jy¤¶7¢£Ýñ–ïp™múÈ›ê—=ÅšòdØè.f†I )äíLìÈ“ddŒ£ ÓÔÆû}=ÎÅç E[ez$­¨«j•Ÿù[>zbsZB,% ÐøÄôµhCí|9½†æ~!•ò‹òPÊñ„Õ`7¡¯÷“(xk}†Ør²wC–˜·]ñjó‰4|$%o×F~&0pËž©õÔz²Ãž=…KcÎ.h¢{|•±ÓÜevæÁ ·ãûÊ®’”ö³´:Ny»&™½:Ÿ®Õ@dôÀÕad¤@1ï4}ú’H"rp9Æ}úfnöÌ‹d}{ñ—…}R¡­¦ÆPQ³c ª97³¼Œ>G„pDãr Þ± @vƒ‡§ï©ÛæçåcÑyâ64ÕõôÝÒ±{Ðë«>{Ø(o/Ђýƒk b -Ç’ÛÚcí=föN±àÄã’–%Ñ­OœžTБ㫈Ú`е~çLØ^æ°ôûéRa×u-³ÜGÔ)ÎðÀ£ùiq“ËÏ£Dª`á—ãç¹3ûç-$=-Û[ØdzEë ¨jé}ÂË}LL¸aþ;u½‹FIb,ðZ/ìíLßjèAz$:yh@ÿ5‘l ²°’¢Nn(2r‰1oyÅ.4ðJgq~\ÖŒn-nuq·ÿÁ$’ÛH¨:šyÄ–Ÿãv!N;YŽÓÝÒ¼Ö¢hÄr±èZYÃÿç¢)m«™>\œWŠTmï@‚KiK§‰\E”u— &1°Ódà;áiE&.øSÀο®!¨ÇãÉJd2έ¤Z`׫âƒÒ(¬—ö‹ófVh¾ˆÄ)¼TZ q6…sË=Ð2h%wtÄ›sÚª´5>šE/*bÓ}tþžGô¦$Ë’Ô=%ÚkbÞ·Þ¬·½Ë‹Ÿ"¥†‘Íß•Y1év¥¸\o¦ÅXçIÄù>€Fã3óç~6\šlå69”Åå*ž¶³´!¦7pþUkÔÎŽ„ø8Üc_)«ÏÉqsòýg4\™÷˜ÞG´h‘œÔH˜ÙÕ‡þPœb©ZÁlnöóK4ÄÂÃÀf1ò!âú®1úÐϱ·au‰ÒØ}:é®t4ljôÅÖU^Ü¿‚Fzxšóý[tω+C¯ÒÓÒdG/"£Ð×·­˜KíÎßý4pVçoõ ÂÙ-]"°|ÍÌ ¥•2©dôÛ—ÔR§© úÑ]´ëû¤Ë(`FÈ@ý­©”0‚Ë8<¶qX¯;ûU‚&0áB ­è ›­¯z('Z<¦Ù›ŠKßËqíFIxñ‰ù/¶â3^Áñpìe›T\hñ7’¡uEŸ‘"¤v‘F’(azÕ`f´è]Ñ÷ È@¾ÌØlÒ¸äØR;Êaœ“³îyª›Áll8Ù³¦ªûà=h´; „Åzñ“Q²Ú¬{J½žoMë‹^符oÖ]È*_]6ë÷”Ò=¹L7Àf0n@ ¤úYg({Ï`kwÙ‘3$ãá¡/8J÷Lã¥>5¤—ZEõÙè³9,ýå¬ «[t«Ò8˜g)ŽÆ—%¦xȰ¤áÑ€G½•W•S¦€žÊß22f¯U»ÿYàÚ;œYJ[X> ‘ ?9»qWÅÛ|ýÀÈBÂÚHÇšz'²†£†!>3lµ,&NW_Foª‘g‚5¦®ØXòGWËcL˜Uqy|B»Gªß° 6ëŽáŒ~håz»ÝŠ#'Ø¥ù“!»AzQbßö«­/mQ%§1V*­Uô4”»¤Y+HöÏW¡ôÝ&_6Hž¯È|Žw¡ù ÷Ò·«+,‰x¿Ê~øJúå’p%(_bsx_Ô$Ï+ øs³F]¼ñ䈡tF`þ€ðZÞ§b²ñƒ„Û±kx½ko+†5ȼ€â3ÐÍ–€.®+¦;Y¸u)X‹»9’bQÐME?^zd“¯Áúð.˜Ó |ryÁYú`é8Z1CˆqY‡>èCêÝ<›m÷s\\Ôò5S 5!ø'¼ñ`ŠðaîalYïW€q÷¯æ¬@¼Nn-¢yžÇ-ˆÂ…¡;…nw×3³=œíˆðæi§·£)×¾À•:Ç´VM3¸&¯™=úªìšåcÍ#ªuXy«¢fvVÃËÿÁCpõú¼í•;œèíãÝÞPÄ7g§)äúêmyDVï†7šD¾:(~`ܰ˜·†íü¢¤ÿì32Zâ‰@}÷e9wÆ+×B«=YnZÒ:¡ Ë^üy½^ܯ‡î"[¤•ºÌã /S8A»Vpd`ˆà&!æ,âú‰\h-™Í`s—¸.pÚ魺ݩ;¥–ÔÓ0A g‘ «e³).9½·/)04n8éYKTv:e{&MNÎ’ûˆ¨˜§ñyºyЇp{ö°¶6&õ1´Ò¿ÔbA¬ÍÈ Pô¥¿M/S}_4m±–±òJáB ¾b¸ËÆîF#wÃðh¦Õi¬ü§Lßçfüž‚R)e[‡+ÀËU †þ×|A=mQÅ1LÛ§o£|µ¦øcErÒ5u?½…Þ}ô¥Bˆ£c·L¹œr¢¿~\ÝPç;ஈ âRʼ¬$í"ÓÖ­l} øŠõó`i@…ý㈞%ÿgŠí .ŒƒèÛ€ÛÚì'uXKg‘´ÖÌ  ”5<ÉüÌ.ÙqB기¬nZd{s÷èØ’DsºÏ-c«Ú*¦ƒøa¢â•hBÅìðƒäÛÏÁ ú›hÑ¾õÇ1¡U)¸0â»NºnQG—*ÔH[ä_çA¦ä]^3®6&ØwˆŠÌÑŠD{†t}>èÄóEl2ßi(¦¢·0aÖ¶é’Mùl ì¾Ú‘£Aãø|rˆ16`êÃQN ÒÛ6Ó¶èhû5>®Õx'•öK½:0Ú¶×ò\ÌhâR6Þød7f¥ufR÷\ìÕGx‘ÊÆ|9‘òQ×t»ž²Cü¦“ñ²` åê-ú^ܺ°žÐðjpY§E^â¡52"†.µÝ7#ñNÃŽ2{Tp}¶ð(èÛÂNv¢¿¦ë%ðíæ =¨AÂä³ î,žì£îˆ†-„ ª!¿Ê®sƒ÷pä)ÏÖ„*¡¤‘$‰®ð–C}‚RZo· ÔÎó žýMÕƒþvjxÃÓøQ£$ež­Ìs¢eŒA" ö Éâř頀L%‡5tØÌºÍŠžŸ¢MšR¥ð/}3ŠC˜½)Íœ\<ƒpIdÞsQ$^£¦›;¶cdbš±ê¨á%ü±SØ›’<žÇƒ--âI¶è*Ý£ü„nì¨qŽü›ã ž¥žzÜYô: ·"ƒ¾4v…äCŃf»m^‚(µ4㇇‡Os»6Dd¤ýö^›%”ÚHÞòéWY\Ö ï~EýâÐß±&DØÔÃ4?ã»|¦PÈžÕ9)¨àdžzsNÈà¤û#=Üc†íQJÑ;\?YÒÛWK^[à ¢½¯7ãn¯ªô¡Ò,ñ­lsÑAî1Ói<œìüˆÿ5e®‰Ü.-*/¯™¢ÐOššÊ×T—Õ^Óˆ¤QÂH#«¬‰@Z _žw”¹'žÖ€À±³ìåw.ö¨0ó½;“ÂÔémÖ{"ëŇƒÁô!T7‹z°?‡ «ŒðŽ;퇆çÙd(/Ùׯ|f…˜ÆE ÂFB±î¸«DÔë´ßK¦~¦øg-ŽB¦d¥{Ðê“ Wõ8÷yTâµ|Û hÜÝ+‡_)ÓO‚ ¾Åñ9©Ër]9Ÿ/0Aâz›7O› ­•êÖ^ö+æÝ[b¯zŸÂØæX”šTªI,ñ¶€küû6GïïÕgxK…É}#Îý‡IߎV·=‡ýÂ#x4”ÄÓïL$A™B…Ó£Öžxæò•à ¡%°'–ÑvåœûºoP2÷Ê(ÂIàÔöÜ'\ ?¸÷ žnž}ŸqEÖ:”³–VT!ÕF ñk/s¨µ$k¤ÿ¾’@ɰ’Â[T“’"˜<ÂTšø~J`‹ª·y¿7Ù+:Ò…ÍÃïÑ$9:&²OMSå¢k¶í–­mš¦aF0oⵑÝf¹>ü^¼s¶ÿarøùZqCxù$¡‚%î‘®c óRœ.­ßb¿ÎámýÎÌ­Ê ÙÌw‘ìígmf<ðò2šû ©òqÒOI¶›…‘$˶€Í²Q£HLŠ„âÍÐå·eó¥rR]¬I¬aÐ'L†TëÛüBaehôEöo× Je+œ ÜƒÊEAÂ\±–éшޥý¦ãw3­%êT¡äO¡¤X±6Ÿöºb|”Ö$üܾ6‘ýpñ©K„9)пçs«‹VåúÂôˆ2¦Û*8†…ÿ)›Þ*&H`$ÈËÉÁ+x7ë:PFø“*iÌW!eæ›e„y{×'jMôÈú˜Ï9MÌOç€à Þ¦{ƒRݽû‡(Ô±R½ˆâ?”v~ìw*VÌÐ:VÖdUêO9Ù9WLg Kw2xhβ0…ÛeùI‚½[ÃÝSÂæ¿\Êí ï[;(ŒMè QïÉu,ñ6¢ä Ÿ”#":}³mŸÃŒp¯«ýh-D šÓÎG¢ 9øƒU _9¶[ E•TW\†åáÎô§ˆš‚­G$Ó”‘€ÑIgQomã/؇ö4ˆ%Ü\ÓRKÖÅ À"¡à^L}eߢñÛ2ºâURuµËî&[¨oòÓ)§Þ(d«Fô8†:õ¶Ä2N•IŸèL‹_ë+Ï![¯‡OfÏywèGšdX 9M‰£ª‡IužÉfÑkówlÛ¡Í›N–ý³0©“l^ƒj›WÞº•ÑɱùÖ{bó1eEÁ0X„ˆýBº_HmúÔf¬”;—4ûÞÿVîÃ1:Î>¶¾åÁ¥P°¿€©hn?ŸÕQߢ´ubDÚ!ëbƒ#%Àt¥5æ3ÌÚ[pî© ì› ‚ùåkv†Fœ&ûyéƒvµÉ/ª `M‰výÐ|KÐÇ–ŒXÖø¬ÁA>wýÎÞ¾HjÎôÃ\W×w×ê@…€;¾¬ µty ¶Eùý Kœm3×\-8âdPùáɆÓ+âB¾¾ØÂc§A*BƒQŸëú8ŠnmÈ(à£ÏpMÅ ¢Uÿfñš[°*‚¢®ŸÒLfÊ2×&Õ©´üä<©E1ÍxP]Ùêd;øHÖx´"-ÙU‹ˆ ¤±‰"H3?·_D"̧М7 _ã[]/ÞCj$˜Mº÷èî)F~æëãPŠÂå˜àìÅ&iJÝéï˜{EðpSH»šhÚCù&ÿ20á;³)I¤tÂ+ü¦3ìæÃyш4®û/µëÜi-¼]ßJ}nëd@Í´>(Ò­ŒÞZA6qrtô~ɪÊ[v£;̬í¯vøvuágÌWÙñÕ<Ö2Æ)òQ€£¹®›ïgŽr¡Durb«Š ö²t²ŽgÛ;òÞÇ0DÖqö]0ß³uZ7çtm{NkÙ¸ (ºOT¢6z–ßšÍ%à¼}å-]X¨C.ò#2‘]>Í}´Q3 žUR¥32¾åP»®HÎ`Vïýa Œ â 9º†ìºïLt\¡o"×ÓÌŽ$*c½[Wö„Ó§65-ظ4ë8¸OÅKNåucòZ—è¼ïBHC¨TW"Hpkª óBü¿ï¿óúiäÀê›OoÊ{ô¸Ø^{›X´¼Kyâ!Qªz"Ú‚}þ šÀk1Æ·ž•à ‡ÛûŽ¦Â¹sð€  <]¡ñëÃ@Cjе’ÚzÂIº]ßò2æç]õ>_h'k.A­¦;äêN[þÁÃT_^O 7½ÁM@´×½ª±Eœl™&³q+ŠGd::Ì OÞ›I§\4:§N½ŸUØŽFæä¯eJ:ÇÄß°¶t®˜+ú[ÉLM[Ð2ù®EÖßïîÜ?ûÞšÒ£2 ]£óxK+º…ê—"‹šÉ½O¼mÛ#À$D,O>äåjz ¦¾3ŠNÒiý¼ õD1½1}×4æ—›é¶TN$ÊZIÔ>,~G:¤4¾ìTq-ÌÙ#¸Vlnq™tžýÓˆå{½òT._(ì•èù·¼ht:?šêRghú¹‚(£.T幃;ã ²é¦KøbÑâÞeIüé°óE\ñiZ™OaIVIÊeŠT’Rø~Ò‚ÜeûjüY‡@7-‡"6½Ø«ÄÔ¡’ÂÏO=ºEµƒ&;£=sén1ÀO»±O¯u²'Õl¶Ý4б2·D|Xnu?÷jÐ §Þ¬|³Vn~Lœk‰»,²Ãˆµ#D¢U.Ùþ‚öÅ8;!:ÞDË¡.*$á\K¯HKlÓhðÀu »î×ü&Bh]|s\~£9 -N‰šp ¢Þjè@ñü.|é ë>àËÑ”BõÎqˆë¼ëõý²©zÞúó›«Ãç±4Ø)Ü8”@gÎ"ýÝ%sµ~ïåãXÂ3>g„ÊP‡·šÔˆsÉê.,`S¤¡‚ç$¾ïò ê´ÐÆayòÖ/®"xiqîtô ‚ÝH“ GJóŸÃ¿²ä5ú6)άT ð|á¹8Ã¥K’åœk«Îœó½\—ãR áýy=D†NêJÁ˜MöjNïk\Ê5ÐZZ'fyC¶®túq™èÑ.n§ˆb{ã±&dbCÓêc·4L¦±¶QU‚m¾\„L ø ë´7‹gk_p¶Eç©F8xh˜ûUG»xFÜCjZ S™Ý£Zðù×âÚ>ùü®¯EW(çÖ±Uño0oBòÓaÙ«ÆÇs#•Ž1¤æûHhÁŠ,Ï­‡02‡é4#o¾«úÎUë¸j…ö]¿§†º—Õ 5™ gˆ÷‡F.wò!6A°º}½Ä¼/úôdá@Ó¥ô> V‘DƘ_+öD2} Q¿ÄðÝÝ—p)QÞëMmýÄ}­å¤~´[e×Up† ‘JÜQ€¦ß’ê"« Êk3v 3ž³0R»f’ZlIj¿S‘¥Sv»-?YÛ }¥.i[¼ŽGeW@®WUbêˆÐpÔ?và—P/D|“‹S]wù²X!TùGˆâ1›üà¨Fã­‡µ)=ÊXÂpjod<+tŒòYC€ÄC-h#Œï©<ÓŠÅG +Š Xrä}\z›5È%Npãï:÷¬ê;ŠæpŽm§blˆò£/Ò/ÒÕÅãø¤UcŸ~ÉÎ ,3ç\ƒ q£ I=ú Ç]åß[ÙÞҘ$ÉÜc<ï ŸÒ™Û“Ô5Íh:sµ*ëzyN@RðÇ:5êÚeÑÜ ÄÎw cpC·M"éŸÚÔa´“»BX´ïqÛ^iò ©„ÞŠ0d£Ív£SS˜?f“ôdxH{ ¨<è‰Ü9±+â eŠuÊ1µûSœ¸€³ âÆIcGñÓ>™6“3€QÞ-«*¹Yiá”Ah{ç`1é8h¹˜³ã]ñ…5+#«)u Pî†Èq­ÒÂÞÕê ‡i£æVxûM÷¼ézÓÔ‰© ìÚ 7á+U%§„¬Ñ¢çi("wú\úυƘ?©˜åï ]?mùZû"Œ"Ë1ÜøpóÇųdŠtgØë-¿þ±ÃÂ$þ¾I‘K%MaZØÅßù²Ã@ CZ+€C¸z¼72Á•a@ÇTHÏŠŠqÝqxÜêóóDŠ00â› Ò™(ëI‹8–HËq$˜Þ˜ˆ¨0¡„5‰ï|‰Ú‘°Ã0*YÏ«F8¾ýÖ^¾O& U ªu!¾h<*Þ„«- È+Àb݆X×™Pî/o»ž\u-CF’#bQH‹ŠnÚ˜ªYôDMÕ× Ë}ê†kDÕw¸}^¨‹,ƒ½±fýdõGˆï¹=€åÑÂÐÍ{ÝÑDAXJ€Uÿ´a3¹¡Ú~)LïwdÜÏa¶9éùîÐéÖ9a*\¤@Ò+ª 4÷Üïxï»ýƒ¡#$5±Y{òÍ»®RuÈr&¨¤Ü“/î,¢O‡¿l8 }ùL‰Êuï ˰è-­0mfƒ‰ âU¼‘Laf$>,Vyý¶°Ø(ý*ÏkìëiÌ4Í0‘¢©0ŽÕ]íI|Î^ø¯LÒ‹Ö)’B¹~. ûߊ-¨îlÙ¾åøÝÛÇ^ˆãÓ[SYˆ²n»Þñj™)D|÷¾\zžëÂtwKg²ÜV]Ç_™|!¤ó¸Ycâß*ÓJ{2|[‘–+#(£s Y}gå WïÂÉBä‘vù!§°ÉêÃØ–A c?#Ž‚rl'ÇT/¦ÍGüªÅ„ª!XŽÎþ•Pzã¡ðÿwhÂM¸29> stream xÚ´T”]6L(ÝÔ€tÝÝ]JÇ03ÀPÃÐ !%’Фˆt*ÝÝ Ò € >õ¾Ïûÿk}ߺ׺ï{ï}í}öuε £ž!<n U»"y€¼üEm## ?€Ÿ_—Ÿ_‡…ņt†þíÇay ExÀà®ÿ…PD@AÈ{ŸyÔ†»4<@APD(*ÁÏàçÿGH”@^0@› w…zà°(ÂÝ|0{äý:ÿØÁ ¸¸(÷éy(¹´AH¨ËýŠ`3À†A‘¾ÿ*Á.å€DºIðñy{{ó‚\HnÈòrö€ß烼@0gí=àÖAy}èžá_ü<À˜Òƒ×æü›#ßï2÷Û¬ì Q„»¸@]‘8¿ûS‚! àû}÷åûëp\áÞ®þ[v0WˆÝoO7¾'®0wO¨ºÒ_˜{Î|öP$@˜ŸŸ_LPu@}À|¿0òuƒþþvßsôwƒ»ìîi@avÐûŽ¿È @"<¡þÿø·… 00` µ‡¹âü§ú½j÷§}þ˜Àœÿ^~@ÿïçŸ?Ë{…Aà®Î¾ÿÿqÄ|OMŸ¨ÊkrýEùŸ ‚ÜàÏ#à ŠDÄEÿ®¢‚ýÕÅeª»ÚÁâ6{¿K7ìõ—ØÿÀ¿kéÀïu °ÿGæüÂüàûðÿYì¤üÿiüw•ÿ«Ìÿ·#Ogç?âìþ?q ÌÙ÷/Ľn=‘÷3  ¿Ÿ×ÿ…Cÿ\m(æéò¿Qu$è~ä]íÿÙH˜‡ Ì у!ÁhãO÷“ßsæ s…êÁ=`¿oŸÿb÷Ãvº¿=<î%ùGz?;ÿ^QÙ ‡ü2aùâðß+I@X༟FÔçøx]áÈûÀ=»@€óûHEÄ|J¿]X¢â>Ý,1ŸÁ?Ö}y¾?¹ÿíð9øº9Ü_ÿ€ø|Hoø ÷åý ˆ?ÿjì‰@ÜOïÚºgõ·ýÇU…ú@Á8 ³p°d˜cuXëåyož­Qé)–-ã ÿÄGÏ+Ì4ŽÊœÐUÄù´N¢¥Meös¹Ï ¿üšj1#›Sô[®n¬“ &¶ZpæÇ)zÇ äkzè°iyŒä¶~¹< qBoBmÓ`Éw÷#Ð{MzéÝ­êSÓS¶81»¥¿])¢‰{S6É÷$Ö"¤xš¥ÀöÕ ’‡‹“䨇púüÇIÞØƒFNàaœà[³5øŸ3~ËïŒ<Ú©™©Í¨èÐÏI†'Xýv_jPÎù—Å®JÏåòsð¢¬÷0 µ1I˜k©“Pò;#ÄU‡™[jøBLºð°s¶ mÜ8«Ý樸켽UT_ë6u[m÷Gb_D!¸ Ú^ ˜:¾þÛë ÎMÎ5ŽªÇÌýÍí6°q6È—–•~Eº’icОm‹µ:f—2Wùw9ŽºMùlû~ì-WþêI€ƒY˜–IHDZ˜U/Ê2t^E*d])Þb‹‚mÑÁa>@ýYåÉ"¯ûÉö­ÐQÁ°Y†˜æµŸ·7m¯sêX‘º°-Iƒ#8éÈŒüAf4wŠh^áì@™f•Äåc9EÈ{¹‰•CÔíÈ‹벂kñc{®ê«é†]™ƒèÓf¯"AA 鯴Ñ:çdÑj¦|Ÿ7¥Ìª{ w "{RP)h”GÞš²æÇ©ãv íÎ\üÀý‚ñ’ÊÁÍÉ®!JǼ"‡…Báf`ð´R¥SÖÞ S³´ÆòÅH¢”á”^hcûa»·ÒçeæÃ´]) –?Ë6›ê0›÷ô鯌­Ž¬ê 1fU2OšÚCÉf%©Ûjž‘d§m × üø)iµ­kt>ëÈkýk4.ÿóCݲëvœÕþe¯wÂÀ”vçKã Ŷéût²a™Ã%|^Äé»D7;~¥ö¹ò¼½W’–û|•ŸÆÆy/‹ ä¬ |МFwÉqþaµÄj¼L³ÜçOßðúø—‹J÷£åoåt¯jÓÛh>Ïd&ªh>S§ˆx+*Ga$*¿¤}­«GÍ+¿œ«6È‹0©Ê• ¬N¾Ì%Ûvì159Wžó,gh}#Ü×⶘¨ ÞZ´^m ¸)ÍuÓÿ'ÄFUËœž:ö4?Ä÷6ýØõ2+wë•@«9r|r`ðåç7±µ9²g™Ñ¶9ë·œ thÌÁ8Þ·6Ñ̽p¼ðì!DL¡ù'¥ñ¥O&¾õ–ÄÚQbü,'Uª+D^MCÒ;‹ó¥ßeç|o ⢩/üê(ÚÁr“»K§Ø í'æ Fˆ2âCwzôdi\e¯ê"± ˜ŠT lX~-‡?ñ:˜HÝõ¦ZÅÊ@ö%Ï«´W§Eîa˜V9Œ×±hœ@{ï‹ö!¾¢ü¼FÁ6¹ò ‹¢~‹ ¿ý íNj޵Ìãï!1Ê>¡¦lÍýeûÂQ*à iWÇOg0fÁd»‰Þ@¼¸›Ëá]Á`Û,Ú° jî—•A  ®:p¤_)â¡;ò\…c…uꆉxûy&ÊÙ>ÇŽéÁ†ùÔ‚{—m‹$¬ˆöZ|õÃ} ’ê„ÏMÖ2ÄX!ø@Ã}CÈÃ3ª-Sæ¯á6…çÝTs£)¾¶¥[â^XŽ«¨¿7rò9Îv´·ÍUK`ñ²Kàtl|+Ï¡åGKg)tso+;“¡z'cµççÃýÙß*yl‰ÈÞ¿oˆ¨k:/è_y‡TK1ZRü56HÓ•wß±ûÉLæÛØ ×BàûK۵׿cf¨\örž?gùÉC@rUv…„x¼¦ÈVDÕñ×·d_‡ «> šïlÌ…öbè¦!å´$¨Ñ›–¶~lmý[c cùÚ²L!*.œ_hEž«ÒôF§W)jQä¨b%¦ë ®¤ãcþ7U_"ïÝç;ÝhŽvzJ»ì¹mÿ%(õWAÌìW¢@6!ç´ñÔ-¹Ÿ•mÖºê«M¢ÔÙc|þ‰Vü|y ˆ*|;š‚à W$¢«³'—asSíµ†¯J7ÙòÑøùS7ØÖ½;éÙb=ë A™Çá/¨êìº,ñ£ÙTŸª` Ã7zÞcPÆ<Åý–>´ä/W¥ðp#„U9C¬£&³ïFÛûÉEΡPúüçnîœ5XQ¤©Íj'tÞÒ”+ÎýL;©³áÕ³fšv¿¥f©ß'ÛŠãré¦o"hò”,›‡V]<_EŒŠ\êîQ+óÙÖ™Ï4=Ë"¶Œ~úºö+u>F-ÁSEaõxÝþñ:~)ÃwonÃQ\GÝâaF¯pœÃÌ2!EJôÏ/Zô¶ÓäÜ•öº®lbä7ýeï))OG°IÒ݆)‘›9ƒAlÔßAf½çÚ’©w?D2ŒÚMʽdÒ§IõvuÌ&O™q0^ÔH²—Œ?¬µ*r'”cÿö=èªCXµ7 *FdµÂ¥a°Æ†¤s9—1ùÓÃD>X{!žê.R¼ŽÀBM´Ãx¹“Zæð|Õž/Ó§¥àƒÎÄQïÔÙS{ůdú!ådÝpMÕ15ÍCöDqšºÏøf 7Ì€©ç“º06BÝJ)LÄ_;°‰BŽêF%ëõf9'ü0òç´à7¡géWø¼•¯“W-û?5ÝúîèVë¸6Õ¤¶ ÿóÊO¥TÆ– („Ñ*4—2#Gýò©,½#uÇ«R˜¬m¿9GJÞ­dgÀÕ–Öƒ¡Ýy”/š$‰ÑÝfM»¸Äg-J*WTjíw[æ¨T¦t~¨Šl<>ïoÃl+>¾¢«-ÞÚùÐÞÒKXæ¼Cp^Mó3sÐQrf(B@ñ3zûZøµ£Q5KÁÔÈž(ãÆgŒª@ £#PÆhThT^ùšyö´}^QËôí±I‘52X À!?Kà¿Zrùmü|îC~Ry‰Ÿ§þPiºáœÁ„“aÇYçˆr>Á–Ôq ²” Íû£§uO1:-ÿ*•à[ë6—.it¾ÝÕ ý“³O»³×8'lêØ:^·lȺ;–drà ÆdMUsåÖÈ“ôMÐ#^o´”аª§*ŠÏº t‰"ªI¾«þd‘ˆ<Õ@ÜÖK­°—Û«Zuv×Ö<«ôÑÛð ÖÜX™¦¦ìX3½2 WJaºlLe&“µk¥OÿœµHÜ”l2ô¾µ#x“öÁe =–çs)®ò)yc0Fæ‰3ü-#¶‰å€‚#®ƒ$¦¦Kmñ„·=F¾h{ã€Íê;È2+ö›OÐâç ÇÏq'™.P®«×>õJ> OòSY7úaŒ9oH«6˜¡±^œ»Çñ쎌%§ØÖ¼XW¶ë¤G’<ÏÀ;rµ©O¹Bø,S®ñV@°äÌ{u‘¯qh©&hlè]ÍŸg±ÔþúòÞ4ö‘˜&kñä0AÏXA4£lwá$ÛúgWÉR{×í¢Ô¶òá!y™Þj™LëŠì\ó±¡ÙH0ŒMŸ|D«m«M*¡oF%?³UGe>WåN»Ö¶ñ TÝ/Ê¡”å'/=\ùþ2ëNt]—QLaðc¼3êïüœ~Œ¢nÆ3Ê G³!ÌPv„ßLªŒ®õTÛ*®Œ¶>û-_Ê$ ‚jâ[=ë[kæÂf$ø´&å¢ÚäçkÏ/.S\ËDÜ+:²¨€Ž¾S¯Ç3ô PP7jˆ™ö:%Y€îÖ0`´8y93TÀ.ùÝÝŽ?âèû L à›jWúQ5™^~';Ù=Ï¡Q 'B 6%}ÃÐRÛ‹ŒfÙò§l• Ÿcrz¼NÎõ ì¾Ô–g1Ú[ŠŠg¯_¼O=çŸdBdÑxd*¾ßF“îœôÄ»6Ÿ¾ž¶’bä)2ÖJ]Ñ&&V瑹¥˜IUÿŠŒ„<Î!ÑÿÊš©ž€þ¸ 0Öc¿ZælQ Få*© _R1v…DhŽ˜zfÚê¡7„Vxeí€e­íµ„ÍàÝðe²/´%y5Ï'íò#ПQ®©vÊLßÌ׌Dqçå¿ËØ´w°DS#mEÏÈ›·EéðÙ¸aîŒnì ÀÐK®CØì|æÝr›’ŠE«(– „ÈæŒÉ9~˜q#7Z«bL4 Š.Åú‡/LmJvl4¬*×èЧÝOöHÅð%xOÇúhÚ8»Û´´/Þõ}ÛɶmK-ÒÖ¤NùÛÂ5³Õ·]'ž„Ái¼gìéN“;fâ’ >¹ÓÉ—³]•n£^ÍÂÕgŸZtc.ZÂfìûcâÌ­WÍê¬#hß¿¹M.¬,aÓó&ÔŽbÁäR–ðŠÅ‰d Coœ*ûV´ž*ò¡3Å‹·©qÁ»¨í…Æ~ûVÊdë±s—áî~dæ:H×U’-¸Ý f[eß;¿."oH3ül¸Ë«»]zwõ°2 }CCìX&Xj'€£“\'!¨¨˜(©K4èÅ$DÑ_#/+.Ý6 Jž¢ê÷'»ºÒj‰®ÿÁ¨µíêùª(ˆê­ÐbÞSóá5.Þ×Öá¶û%ÌÈå‰À}ÞúÀÙ¾©ðÄM¥ÿ—r)©l¯Ã‹¥ÆUŠa¿Ù³H©+Ü”“—ýão–Qć+Tu!L9¶¡ÈúÌÁ fß½ñ²Ù‚§‡Kã—T³“Ó2o–7ùÑs‰Ïƒô ’Œ9éÌz³£us÷ C‚±økö‚g@ ”Í¡£³íÍ[†aU£i<¢/B±¦{)x:²9)Õß'øû›"ä£3Vͺ¿àí>k rçÚ2EÐD{:ÛbÓv©¦§‘ÅFä¢4W±·eÆ–ßeúØ QµåRŸëƒÀ…Øã Ŧý¾ÜX÷ξ0L%ÅN¦_&Øv^wò1M±qׯ}yì-ë€í1h𼻞\o9ÀëíRÖáÜTw‘°.ðNåm™ö”°‡*i9|C§yv²w˜^«ã½ºài)<·xClÈBu93ÛѾ®[¶ÝŽ¥cÉq;>áU‹–eÍj‘Ò|±ŽÕÌ‚˜'pTˆ²°ÅœS,Ó&èØ¢7jûëêÙ¯ˆ7„m?Cu¬G2NR>,“­& ^Ž7…>Ö‰rÊ7ÀJ8&'uQ*÷D5Ìx°Ô½Ñêú†7Q÷„¿u`[öHž+@Ýð0¢IøU©Ò­¿ÞE2Kgb}=i: Qâb²›gÚ– !päGÙ}IàÞ “ˆÎæÊt%÷¸€ ëÇÇð™xI|Ìb±Dö˜¢Gð;²Ît¤ã8õjíœÉ¯ço¿„Œs]ÖÝìEõ2ß)MNŽZD}MX´Ý)U7Çä Ñ¢ž‘L[Aqß,oMIN×Áî”—ÉÑg*xäF ´×[ìDO=Àœ«}J?À¢NûªœšáHÈë8~¢•~«2 Šî½g‘M*òžâüÕe•ø"Y¨$¸4«aÝG1Œ‹ëYaÔ ^Ý'k’ëÅm5:{E5¢Im[›o.¾ž]“G;ç“ýc=?~½ñpþuˆá’ÞýȺAq(m“ÇË7t¨ð=)‰«…9%FmûáÏC×åž›;yõ û€¯¬è¬¯¦çYAùÛ†#$RÛã ›YCØSI#ÌI­¦ü}:Ê·f [°ŽQ`…'Ù/?«OëãX>\O{‰OðþÚ›Hï&Ë´µÎר{È,K¡wÌ5×I ]#ÎÖ÷$Tª¯éêôvÑ^aŽb6ú°‘L™ïgØs²D„5Š %Ë µÉ»&8Ï«ïÈz>õÇ?¶é)‰ˆ ðü’“ôV°{m<Â6PË4. SÈÜs”‡3Z[Øs‹‹ÿž¿ÿ;1ä˜ymuö¬UôÒägwUvÖxYC„0ñiKºí“]©¼°gÂÔIs¯üHH2ƒÇƪðLkváá–u!!#2ë¦- °´ÏsCãLˆ<¹eÈÒÉÞ¥3›÷ 'N:.J?›Î–z´¸+]Œ¹þF½:§Öí=.µEëÙ¯€Ž¯¹M8…¢:¯E~©¥l:ïb³ðÇ›JìÐ&>ÕÞ4U#°ºv-/þ*z¡êGEø}öÒkfC³‘Úou-)F•´Žb“¢9!!™ã¸¯7¾àˆ³ÓH;¡&§µ‰¿Ç(;¬ºæÚíµoHÙA¸é?V¥¥m.ca¾˜’Þè:EkrüГ…²ªÄÌË–(JRϺÓ_wé–=0¬) @¥êÔ dƒÅ5~‘ öU’ªžï•rJñÓ Œ(3{WŒ0ýèXOƒ…¤f¿úìéÖÛj_Ç=ÃQ¶È–áøínµL°ìäÔ1»ÖF«Ó,©&¹¼PŒS ª\ãüºŸ›JNl®§›S¸ÔV(óz­5Ä$1Aߌ2°y—·^˜|IŽCqÖ£ts¦ÅÛÎ N´&mþ/Y–Ãe=øñvZŒZ!^W†ƒ¥¡"ÝŽu¬Jp77÷IâÙT'ÏLÙJi@®w™'Ÿ¿Læ}¨š[‰a˜ºÐ¼"vYkÁ[/,¶7[E O·jÁ܇ñDá¢SóD† Ÿkû¡”Ù²åÏ èË:SÞ‹~ÅN™Šÿf®ï “Kvˆ@Åo’¢ßsŒÕ) ºceŽäzqzu714gøŠÌûõáËÈ[@½QÑV{^®zŠJõv…ðí¦1åB‹:õ·koº„Íè@ÔØ¹òÙ™-5Þ=—d1´³ò¯'8…‡nOÌçj®·Çò39êÌØvDç7ý«]ŒŠs/¨Œ9®Ó(ØUm …-¯›˜‚TÅ•·èv<†ÏÞ]èëGûDòì~Í%Û‡Sñ&… -xbÖqï‘-|^ _ƒCŠwKätД Â7upÃXA|‚ž?”õeÿ»á­EŒ,ymy~.¹³R%»À>÷ÆQkÔF ”ßkаtNÚº ½óåNãxUïÝzYKZUd!DŒË*Öaœ¡óõkK4¥ëëÕ¥jÅ­‚u4Óz6õÊL ¥ê h“ýU­kxlõyTŸ“p?dî¿Ð€“ÌXT‹IV·øm6ŒÊÙ%R}\ôéÚ5YŸ|§œáÆ{Ê«]QAØqüC[øÁÑ6c‰uH÷añÞ—ñš!ìù7@̪ØÖ+Ç·£IH3;ÑåÞG6ÉñÓDïK»:ºç„ù†7Ã,QYùè ä&H²’4õËåSÅ(¿ ¾­Œ/>®x”^1 Gë~qƒ|±~öÊ—){†+-Ç1Oi"õèlMÛ=ŒÞuâÒ±zÙÙÆÞD"ǚؤH o7Ãø¤ŽçØ8'ÂF\]ÜûÌo3ÿJ÷Ú_ýS¬×–)ý\ýI!qëêñ‡à!…¡ω'¨ÆÐL)< +ë C­EgàGȫ祸1«Àa«k%SãÙN%‘¬"TTr›õ3Qéw ¾’ŒcùOÁŸùd鑼‘F“çDÅ:¯‘æ°£E¯À£o¾cøª-éUX=Š(»S'íÑ„õ­§,Ôä­êŠÿÊ]~Áj —`O¿fùÙa¿© µüƒ§°\zk0˜nðƒö ŒÑ7™-`³Þ|†u2ÕÆ!ÕÁƒäزH„¸Ô=ŽS›óÇÆ¡ÂØP¤Ÿ³ ë2ÚR[ z­|ÉÐýÔUÒì¬lÿ ‚?&Ãíåõ’’OûcßHrE'çPM¤œï[òîR=Ó­>›ªtLm&îãЬ»zö‹Ø‘|F<1l‚­W”N[×6T¬AUóÞ Œ2ë&¢öfÅ%ÕéNÛYj¦ó-NkY×Â^îÑõ>VÆ"±ØddQ­ÔlkÖåÑ®(—Ù ö™ }¦F,ʹÍŸã"vø )Z³QñÈ>2iògâZ%x'ñòKA­j#÷§ ½n½[6è')“žÛN_R3¾í-E‰Ì¡Ý¹àöDѹ¯BU¥Ÿç9é|*£®åú‚HB¥Æý"¸´0ÝðHÏÔXýÕ…¿þ¦ð¬S÷IE¸},»º\V³û–¦qNN|ù&ÕMÙ09ÆøT3j¶Í%?ìÁdèÞ„âc”³Ö=ã•§3d:Øú¹¯Ȧ»“vu>OU!Ô §CQB5ƒ54º`|’Š6×á¤o!´Uì7 $AI¸,{=õS“g€vHdÖSÐ/ ±¢¾5­þukR.ùðüÀ¯Ð´ìfõ@[è$ÎÚK>!Œ¹`ù3Â'bÀíaÄ]w‰7JûÍίB@øÈÐ-· Ñ,‡1ô]^W¥¢Ö·n½çÃÊ~Úhn—Ø‘}ø7­Ú‘¨ñ8ý»½C|ŸÑaÜ‘Ji*}Ìÿ·{ð endstream endobj 100 0 obj << /Length1 2696 /Length2 12540 /Length3 0 /Length 14072 /Filter /FlateDecode >> stream xÚ÷TÚû ÓHƒ RÂÐÝ]"Ýâ 5t‡€H‡´4RÒÝ%ÝÝÝ-Ý‚pÇsÎïàùßZ÷®Y‹™çíÜ{CM®¢Î,j1IAl™ÙYØâŠì66N66Tjj °£ètTj-½b#ð‡„¸=è¥I¡‚Š€œ“€ÀÎ#ÀÎ+ÀÆà`cãÿŸ Ä^ t›Yr*µ8ÄÖÍlfîõó¿Ÿ:cz;??/Ó_êQk=ØhP:šƒ¬¡Vuˆ1äèötB掎¶¬¬...,@kˆ½Ùkz&€ ØÑ rÙ;ƒL¿S(­Aÿ¤Æ‚J Ð0;üÍP‡˜:ºíA(Á l ²q€ª8Ù˜€ìPïuY€²-Èæoa…¿˜ÿÀÎÂþ¯¹´Ûü¥ 46†XÛmÜÀ6fS° ,¥ÀâèêÈÚ˜üZ9@ ú@g Ø hø+t @JT„føO~Æö`[G°ÕïY›–YÒÆDbm ²qt@ýŸØd ­»ë?͵´¸Øxü™‚mLL§aâd˪i¶sÉJü#%¡>ÑÌ@Žn666>NNÈr56gýí@ÃÍô“ý7šƒ—‡-Ä` Mä6A¿P=€Î €£½ÈËãOÆ*;;Àlì0™mPŸ¬CÉ Ó¿1´ÿö`W€tüØl¿?ÿþ2€N˜ ÄÆÊíIü¯³j+ꈉË1þ“ò¿L11ˆ+Àƒ™ÀÌÁÉàæàððs¼þkEþ' ¶'MYS€ÿï`¡Uú_ÀÎÿLÝ?ëAø¯-%tnAº§1×gãf3†þaÿÿ<ì©üÿ›ñßVþ_ÇüÿF$ådeõŸîoÿ>Ðlåötn¡; n‚ÍÿÕý½¸Š °“õÿåÊ:¡» jcfõo!ÁR`W‰ ØÑØü¯Ùø›¬ù{ϬÀ6 ˆø÷É`fgcû?<èr[BOèHþÅAwç¿%mŒ!&¿—Œƒ›´·º¡²A'‰ƒ›àÁÝFë_C `e±8BUÐ켦{Ôß-åá°Šþ&ýx¬bOˆÀ*þ„ø¬OˆÀ*ù/âe°J=!v«ôâ°Ê>!¨…'õ ø„ ”žÔƒò¿ˆêAå A=¨>!«Ú‚úSB\V'ÍVó A½kÿ‹ø¡ø/â„Æ´¶…NúïãêT.¨' t8À–O¥€º:>Ùj=!¨†ÐØÒÁ è`þ/•¤‘=Ðd2uüƒÌýùïµù×ûßdKãäù9ÿ¥ÿhíŒÿEÜЈŒ!VÐû7®ßkë§|ÏëS¢œÐ6™@¬¬€öH@£=…J€þã”ç7ßÎ ºÃO*ÐìMŸT~#ˆÓŸ&¡ ˜=€òÍ~_Ÿ ?E ¡>Ž Z s7[sÍPø Ìâm«åZ‹§y I[ý^¯'>´rÖO*ðäŠj˺–Oe‚º¶q²6ú} šýô„g…< µ ùC‹z:³Ú>±¡>l¡×°ÍzËÅþõ¿å„†Jèuû‡(Ï_40äA…ÖÖÊéÄ OV»'3ЪÚ9AA&FOÕàäÿ‡ø_—ììPá?:ÂMúÉ07TÉd þï€qÿ–9ÿÑ&n¨è•öo„ÐDþÏR°Cóxr ½,XÍíAŒ´PŽ.? 6œž†êó¯×‹ƒ1ÄþÏjC[îü„ìòÇÊAºþ¡^Ýþ€ÐN¹?Å µä²ÿ;‚ÿÃÆNöÐV9þuSBÏèÿá¿> +Èunb,øÑ¢âcÓM™(± óÖ0F÷YÈÅ3íMIBçU?q¡ÛsάÐYÑï“Û¡·«Ï8¾=ÖZêà³Y¾[ñü*€?WÕ„hj´Áä9ú\øçƒ‚Ƕ|k«î{N3üã:µ^—‹7ô/™ìN·¦Rö¤…hêJ®‹Í‘ik~° Ã ‡‡"ðñq¢Ã}lMi.+˜l‘¥r8{3|óJjïöK×÷z÷|,xí ñþ>†­üEÊþëÄÝv"ù÷£€ êÍvI‚»(:¿‹¦¾tFƒ*Q9\D¦gµ9NÊ}íë+6eF ‹86ÆE.4Ô~ð~d0Óû¼Å‚5¯ ö¬¤aÝž£æY” ]“Ð[fÉ Qo1³’¡«Ê·o2d=tZOiI‡§g4Géè9½Ø}q¹-Õ¦ŒÉ‚ÀYѧG_˃ÂÖÎ~ÎzþÌ´}“*']Y³Ñu} œ]žQ~ï_˸[¦w]G4z›ÈfzL©sýõëb&«.CÙ\*ý‰Û!œW©a’4&q©Ó~vö ‰Ê.Âa†B!¥jxìh2'.í«bq‰ªTuçK wó éÜàïI©.\ŸN§¼ /ì —ê>½+š ®+ƨw_Œ»€¯tüÞº‹bq¥êÍ$ü½K‹ü¢•}ž¨¼^nÿ»%èž\§ægêzY²N)qàÁŠ]`¼¹»®Enº~¥¸S œòØ×ˆ=s¼nýUkïí… )ƒ~…Ñ›DÚí£„é‡±×e”¢Tòì*°Ž¹öçM“>Ú¡}˜1úª¾Ì¿‹% {E›\Ÿ79f¼‚‡²Ó¢x¶]ýë"OËþrqËéÙ4‘B:¿ž¯“q M„}í…Hß‹*gÁ_kÙu^@F__ uT˜¯cGô¬i 2÷43’UR„{R&F¸éL‰_J]íº.Êeá(¡P],4Æ22KoRÔ½(¹ RN`½í¶íZÏðÕ'ëÙíŠó9N ŠhIm4¥YPàÎ.ïÚ>lK”ªïØoϤNPsÀûå÷½A˜áÆ$e‹u‰u ËOˆœ¶5µ»àxvûP¨\r 4ËÖwF-=V¶ÅÙ/r·Y4¯Ø¿‚vèÒ­_;VŽ¢Âa¹tXC˜þ†§}‰ÒAb+ 0K~J½”,f./Ò +!¬à»&Ä݇û63ð™H9³sòÎEò´še’÷µËáåEùIî wƒô 3¿ˆ´O+ÁÚ‚ªïËb žœd9r$ß s6Íðç¯ 6GÝbNÙûZ‹?ú…Òjœi¦9Mm‘ EÁ`cü¸L±³ ‡QYˈ$h.eO¹Ò+¦ÿ–?!¥=ˆ8,GC[6"œº»5¸?ic-RÊ_Õ6ºBi°›*¥tQÙ+ùÒ_I8“ðí¬rÕ¤9®E©j5‘<à²ËôÌ=ú9ÞÆ7åvuAý ¬öZ}¿:\nÕY”Ÿ™G’¢Ýºß¯¤ð9ßéž–$çÞ}X3Æ,S3\˾3V©ô-ãÂUáv4ÂÑÜÜ÷'²°DèÿÈic‘ò§½CÓú.ò¨.–«¸ÊO2¯si7JñÜlMÔKu|-àMNCȯ j¤|Ó1š´‘ÄâRbª‡ âàó¢ &,Múâ«;®ª,³rÆ–2©€âƒ¬­Ó°(æ°¤Ï(¼ùØC€]±múÂw½ü)g?µ~ ˆFa¿ŸnÒµŽ¸;à!4öÞK&®EÞ!KÄM3 a}¸û‚§hÏK\ªz7™¹w_>ìò .¯@ù#5…µY¿DÁ̶ʖ>›qÝÆ²Zâ ï<¹œé”Mo©|Bt'58o©‘5õØr5ç‹›"™`¡G7‰ÀÆí¦íö-)Vú«›bª¡šE³›XzŽÈñ=¡‰ÀIí•âÁ鱜c1¯:Äš%Èó±vº1nŽO¿©©í`°ìÔåzˆ­ï0c>çž.K'þT"0l¨á1ú9‰lTýjŽ?”óýØö2Y+ùðúüõݼ[wGÜæË&7zŽvÜ`®æ/#vo¸ì[[ž“7IN5÷pœÓŸ{¢µv(´.çé354^ØÿŠìAdîW-Oä!-g»V:¶´Øv‘5Òn4´6¨pVü©G>ndEY;å½`yÒøOÿròšØtÿX/†ÝÁé çPžÉO±b·†ïõ®zB åV<›ßa«!`Úüçkµ'OÞóÏcøz¿õ-¨Smв±³Ï]½ì>Z8½ø‘%Æ uftþ{iÄY›Ü7CõÕ<ñÞF‚_ù둪©YÙÁná®Ã$¨>Ì5 CŽ 0ÃEÏ…Äó®æìF|áÎB߀¾V%Ï›ý"íK.Xýz}ãtk¤K±¹aF¾ðfʇg´aRÒÁBR7pp_<Ê—vÁXue¼GEŠÀ½¥ü%§ï5(ÊxvÄ|0ß .+Xq7Ð*Èã< D¸(p²%êâ`ŒáÕ“8EÈÌÖÓDaZâœ#@Uß…ycD2‡€¨qr Öé\èXØ{QÂæB`1‡îBýaAIædy‚m0Ô mš0Jå‹~$õ§²‹ÒEš9)÷"@Œû~ˆ˜½`q—¨'¡«sܬ¸q,XÛAùùáÙþ¢Xm×/µ‡aßT×)dÒ•_„¢øÔ×9\Ùg±'.Ú£ô•2 Á‰ìµÄtá/È ñ:µöd Ô¾T©[®í¶bÃ5„x ãÑ0†¹VVP“ô©ÞÀ>Ø{\¹tM°NíMТªð=òÜo]I•ë뺆;¤®wìlÅ+%¨®o#¦;r Huà˜™vLm&òz?ÎáãŠ)õHÁ mª3jz#Mž•x©®—¿Á,øÖ9YtÒ˜<\/ø:ÇÜpï‹. ²YyÓ¸•ÞiZ5ÂHc6’wǰ.]·ÓU'Žº2…d½’œCF“ªÛ:¿½­N\XËaœÇif£W‹×°_Ãʨ”[ÿJÃdÌ1¯×ÂwÜ䇳¥'•å,'Cº)TJâÖêËÜçøG#}ár—0•îŸÕW¯Àa>sNÏ'Òi eÓÅîA™Jô|åDÔ“atæœ_#©©ÄP£9’Ïó_)e±óíü±k¹÷Àþ¦ˆÑ‡é±¾,MZ³ò }KÉhêmÌÝÇÏUqd‰¶¥”hÌÕ±qœ+Ë\œ÷˜eÊõ%¯Õ{‹d³à&c%ß~·çöê-·(a–²gª9[pa´RŠæ›—.02ܶã!:ƈê_ë*‹${q´jˆL§e-ÉɪêH¡Â›áÞרæ#íO“Dd˜µ]TÒ5fµ3àOÍÅåBìR²qŸå'´G!*+ŠlÝ‘:Q–ÄtIc Aø8Ë[‰ 즞x2à|_ßÙzìµ§¯fÈö|¥ŽÏ&I‘%`“þ¥ǵ}Úg;5#Õ‰7±zæ?ܾò® .UíT/FedÇ€p«.~"!ØMЕt.–›[Ï´\õ¥ÑÖ]"ñ‚ÏçɡݠHA,6bz£So‰ì^^ãDÞ»žF¡wŸlJ&ø·$Ñ ?ˆf9©±Éï|‰É¯ å’8÷™È®VÿÐ×çÅ/:ö®Òú¾@YÝͳËÁ~IItYLd\ÏHW)fŒ¦ª©aK_T@ïÄ @ZE%f\”ÄìC>\,§!á28Ø]…‚à)È ,TS¤¡ûc'XßÍÆ¢*õlÿ¾o+q ˜» GøèodOL¿Øgv†òAÖ3yŠZ›tzÙz¼„ÔÈ>« 5î2ÝÕÐHF¶‹)µÀø¼ƒõ“jÂПj°Âf…|%?_îN¹òhÇà(##ÀßÂYa篿ó<ñsY-° Ù¡@¿•ؘyºX[æùëçª&É2~ÿË¥üC[*á5®8<œzSéML„³ å×.jiäÏmàx¦ûÙ+Y5ÕørhS“®=0 BØíÇEY]©Ö-ßC¨ÄÍŽ~ºÊ¢`o>$!>+t§ 6V3hF•d`Ïà­Û1y‰Ç¯ÈTM>bÚjªjf(8”Q÷á3Y*Æduæ¨-ÝVÎx?-‡h"Ê^€¶îÃÀ9s{ØM¨èâ¿§"÷iFQýtµ|Ãð ÇmJ˜ùBû¡Z¯}éyŒžœðÙuŠšà1ÒíÙe ⮇°íÆ—ÿYñ2A-q¢\‚RGæÝI§}Ë㆓—ºÅ¯§|ØÃU¬g¨íN?h3jÈGe¡Pã:Ñ·{…mƒÎÚZÕÀŸ™Ú¯²«˜·&ÊzáŽSœ3[oôˆíˆGFŸÑ+Úh<6Š’¤‹ËW›f´•þªîYQˆdé)㬨¡‹9³‘P)ÄZ*·$=;PŽ+­+Ÿ»Í\Ó Iºz`iaËT ›ÿx›s ĤÌ+ñ#8Y¥8Oä!˜)ZežÏ¯™&!éXóH׫”ˆÆ4yŽh))ºÛNÏ/=æ|~ý&^wÅê'?¤)ßç$O9ø¤–5èù¢. ÅÇÝQûžÊ×Ψ¶Ëú®iîU:÷ ~ÏúƱ·›±7¾?“˜Ðø‘g¨ÓMH³“®5ýÇr­Œœ›ÜÏš:46w¥olñ]ñÍã%‡ucu¾°°Ë¢u3ß-Õ&!(Â8žÛ¸œª`ˆ¸sNR|õusï°”6%œ½+5wµ:1éþ¸‘öóe*.Êhœ$ùƒ…–¡ Ö*¬zÙ\­ ›wL%f´? ƒ„éÁŸÐi<ˆZ¶ilvŸ‡`Mp}y;\hàlj£QtR|ÔóU¸,\z«s鵓{†ŽæÅ^ ƒcXzRäqV÷‡’Î>˜H­C‘FÒ©«w¢ï2äY’îiE 5\,F8²mßÇ6C„ ““ Výsä-½÷o£–b†8ò‡¦½g@‚} c2>â´î{ÆÈfð©v|ÂA9|g8"åæe<º9ÑC:ȳâïÆü:õ7#ßÎ/fœTĸû-1WôðšàçnæDG^ûìÉÛF§ô¦õ×k2Zð"Æ CŠ!@îSËÇ+‹Pwš[÷# ”L­‹éü ¶pDÔ«Ñ3Zß÷ nG¬Lrý°^ÌÝŒqñü>Mj¡»8½Î®r~GÇæ³UÚ0uªu¼·Ñt“”©v4w‘Ó‹ô$[§Œ¦íÄ߈´Å“]Ò$îH×ò'í¦Ï0é;WI¬¦Iİ?ÓfÈ/7 í|#'œ‰”ˆýE­ÿÞZVUœ0릈¯÷«g¸3ûøžßh¤Ø ‘`,jºX=¿ÿBA‰Ó -5>âÇ›õWË‘ÁÒ÷ß{ÆL¹:*רŠQLæ8÷¸ßLeg…$œ´P˜êºØ-Q©àÇ”7IýêU÷æòTÑ\}ë‘Öf_AG®Ê×dXmÀIõÁ¶2€Vgtë&îêÂÃüÇý ÏK5z<ºBèa¡¸ˆŸš&ç±ÕÅa{Ës“fw:<Lj|¦+¤|¥õ¼†í#2í{WE5Öx‹MRjmª®½™sƒrjý Zt?1~n›@•±ÅidËÖˆ~'*6.SÏ({‘´G¾Ñ—T¯+Ô÷ÉiW¨ŸÁñnæ~÷Bvé'>#‚ƒUn¾ z ‚ŒÓ3— ¥_œpï-]SðÂîgqh ~©7±ãÆ=.ËÆ¸ ®M‚Cß)Qµp’ݹFAyÒ¡z!¶šHÔw-~¹´ŠÐð†ÀÒ9U=Øt¹‹»³ëB[䨕Åqu¨YZ¯ÜoTרޗ´Ìø>ýà­WO,©ßõ‰5É!•!ɪ}æÚb…ð˜°Då÷ž‘iÉ|«WvÌÔ—Yw(è3z‹t‡v£•ÃÄn/„?³Ýƽ¿LÕD.þ!° Ëõ5–Ë$Ý­˜Ø<{5ëHñì’]šôEž·˜8Æ·Æa¸Æ UF`á!9aînÉš=z^:òÕ<šŸí-¯Ý_]NU¯6±zÙ~]Œ½´u›Cݧå‚ÿrTj.)àŽ+‡W/-ù¤¾r%DÄêç~qŒ¦ CÊb“äfÁÝRL~y †9êè|VÚzžÌ:dmóA(IÐÏr’»kžÇ‰±g—o0D¬Ì§Ñz\ñÞÄ`ÔQCô0zMðêØôü=;.3ÕÇ9Vn½Ï©ðÒÏæq up>ëøÆüøÉ&ˆëF¹m^ecRêÀŸÂž£µPËØR% 8­$†&;‡óŠ“*$Ín7½>œ£)Ó¥(—=â=1u{†|PèyÈÄiãk™M=ò|;£¦23WR'Ë—"Ú‰×KLd`âEÊ« ”Ù× ÈÂ'I³›t‰Þw`xL¹)œ„[V©GÎ30êzA~ŸìAá0Æ‹sž@Iû`¶ÑŽ8çÚûR¦@V’I¾“ÞF’äë‡´Ç D×'9¯ vÍ`ÞSÀG³PH>ï Ñí>ŠÍP •Ðέœä\7ê•õBt g!±~/)û¢˜LxÜ X§À#èC7œêÔ6¡:j6üû´? ^Ltõ&rUrOèW0¨¯„ʪŒ]Õ³¡jY5ÊÏŽxÛyÚÕO蹌9ÞZKG{fJ‹à«ó÷´\çc¶ôkqs[™¯&ö’)‰Ã8»žñ¨8¿X$ã¿‘²F8°8ÀGS¼à[S\Š8ð6Ã(}¥=”ä{ÙRÞتþõˆVÐøL3Ø|h ­"šÕb…ÅkòËN®‘žG&O—`Dn¾xj®\0ÊÛâÅ—ò‘1Ì¢‹-•¼@™·'µ ñ/ʘzFtù+&ø±ºtešÉÁAÒÂ\*qÇ8‘™A¹‡ñ ë=gØ©’„lw¿¦¥¦A DèqVlTþ­dx¤2«,R<î„=ç?±I>,©!Û$«îUçøsnaëΘåŸÃæ¤ œ1¯—±‡î)â0^ývŸD‚Mࣳðã[ø(HŒNƒ“4®:+Á¨àcûk]çÏ»°]²iµ|¹OgÃŒ³ŸAHôIø{×À-”ÞÛ)š¦„WIìëd”©øåñ+µ9ÇÁ"ÚƒqÓÃE°VÏ.F(' AöwÖ› ¼_© dzB¦C!7½¦iËkáFÞmj°²¾KC»OîÇ &BAÝW‘r(&î JØ>~AÊx¡oLøˆkö“]INB N/ŠUª »‡Œu³Üáp#)îó©ãºÈ ÁŒ²èr4iô¤šJÞª÷¾Øn–®rþiÔv;w¾ŽÁtù™>SÃÛã:Ü%šZÉʉ%·¸p¢@†™Ð„Ÿpq—æËžV§T6ÒϱOï·,0Õ;å#T5Ë`` ÓDN?Wc1ÜÓJÚë„êÛGœ âñÉ^¿ó°ٶ'SæÄ«Ÿ°Î4‰Ÿûûõ€ö™ôv ž'ÜdÀPŸ®ÞwƒqÕu.çÉéy·Ðlò¡Ðæˆnÿ\”•›Í®|–/R¯P“W<X}ƒÑ·û;(Á¼MQ9÷¤–ºº÷šÎA‹°S-¾mgŸ÷q¿¾ò²òÒ–0Ül¸Eš™“ïù4±Êô¢Jw4±|­|œ1oËõôf0•ä3 ÷¦©Ì¸÷‚¨µ‰¦,F‡FÂóØYµóë”3U¿QëÍ”3ØQ…+qŽÚ°¡EIÜœNZ‚×õ+sg®¯vAž0q/…Ï6b™ó·&T{ÍnJ3xÐKÌØËå¢É8ˆt*¬šQ††¾œ”˜›ìåðowbìB~ö½'±‹Ö¡2žB7@»~?éeHØKÒ¶ -°ybÔè˜{°è×FN€»ÖÆžc'3D6å„?'ȅɽ %Ð2`ïŒr%•éS5Y’+JØ@ƒ~Œ`š/BÔîsáï¤6À¬X9ŽOº µ=ô Å;i|*>B*“2GY‹süá&HLZÆ cJgÿÙÊç&n¬Ôç–Ùjš?‘ÁüýÚ¯íµ4Èið ó¶ª?bÁ{ˆJ5(ÁôRr–ó`ÁÈî+_‘|‰hšp‹YW(«edÜg/ºwŸÓ°ó–[Ùi9ð{ù´œdצ°Ç a0|€ÈÐ÷úr…«QŸÉ“J^)Ê=7ÍÏZ@ÍÀÙ"±ªMÖ›+­Àȳôù,çÐGÃûAª(Ëç7”WpÍ•›ib;5æsº2Uv"Ë9Ý—„§@½†>¢N7Ø×|Á>5TÛ”÷§QÔˆ¦‡ù„Ì,¢Aõ&ïéÇ}¯½GgXhÜߣm™.’ÓÕÕÌrL"„bÃ>’®ÉãO_QfD >œÐš‘g{5#àXÀˆ–—BÓ„K°wKšª“‰W «ˆU¢2à_ãyƒ†Š· Ø?4©ÛWà?Þk;á³Ñ×dy‘¡ßÝ8‰Ǩ—e_F?¿çÉbš<çíI_õ½c©`8|_}}¶ç°ÿMêÆˆf #š–óf[ØÑõ]ã°÷u–öxû'Dæ<qÙõ"Üw‹˜Ô;¹°Ç ÝBªàË!€8Z²Cé3}ÛÔ¯u…&žˆÚÕ²Ÿ`ºÑ>8ÄGf¬ÏSñËXôÌ ½ÔE‹–¦^ÉrRXcNè~Ÿài©6­—‡ß3•X\k÷ÈT}PÇ3•æõû‰žž}î½LÕ{Å: *Ç(‚©÷Ë^¯ª4RG;L äÖ2ËïHI­,O[ëüv·÷…8F'WçêEVÇ+вžèÚBDóì³VJ»Ô~Q¯=ï¤ã0Ìt”»Å‘’ øE*+ŠCá&oT|Ö±óøD-ôº©XÓRŽÐÒ’·÷¢'é²_é©iXY›21Ir“¶» ™A%»‰<,Ö l ïÌ™c°xçVD2Ù´Ö®¤wr¬ÞæN›IºgÛÙvwl¢F·"–+ž{´N’*áÝ^Ê£3M>··é[y¿÷ÁK¿­Ç…æ:œû×wønÅÖÓrKV”%…jYQºƒbÐÍ¡$)Ÿùl5ÊB³®ŸÄQ‡sM™çy‹ÑO{·ß}¨NpÓݱÖ9©$ìßöá£K.k(6™º!Oê× Óûf:©–™‰ÞƒON_‡˜uð_šqÜþ ÜâOd»‘À¯8~1n«!‚þÁTéæ(`Ömü”»è”ÄC7Kf?»Pyæm´)­dñKhÕ²ÓÎ#“Þwf”Îù –þ+ÄÝ6„âMãJJmGþÙØFŠ‘ÙJÏyÿ•×(ñ±ófyþ|iá¯WèøÄ²¹’Y§c…á3{«%‚ƈ-U5âDTé»[ˆã$_š–,4á°5Á®%²  p2ˆ;uÓ¦$ÉÿbMŽkË8xG$f{×5it·S'à‘ÕúG<ÆXÇÐ6ÚjnÎT+py¢ ÞéÙxÉ ÏG;Ø;ïnX·c$uæê³¤m¬õË¥"duÇÑA¹ï¡ëâ !ÁæœnZq V\¨Ôü3¬qe­ëð¸zðcËlûådûlÿ4! p¿NlùT±dù…£‘kÕ6‹~‹,©`Ì€:¶:L¨;PvIóñX®tPZë¥È±*7sú‰Íñ¨ªâ¯ú–X£S¾‰Úl)¡yvØ>ªHSä¾{à®®†CÊœ[¹–ŽÁÛ“²ób¥K¦¡ˆuœÆ­Ü;çÇü‚?³b¼˜Oì8.{­¸¤ã ¯ÛÎJ\3á¸ýQ \[V®#$‘û”/ Ñº°·þ4Ÿù9gö>~Þ;K”“è(ÉÎÝ„LÚqƒåG^”¨ëHäÒoEI¢D•e\QCVßõ2ks8B´ÃXÛ®J¦»‹ì”ÊhÏß8G¨ëd$\¶2±ë.ÂIéâd¬áâo¿ß55ÄË/IŒ~F©Šb™H|°Â¥gx…¿Œ}1‡É`…,Ñ–ùUÌûÖãv3êv| §õ‰LV±Z q·Ý­9 #ÎÐþi³;Ý„N¾|ç¬wf1ØmÁ¢ì†[€vá y,EÀ¦×5½HôW²Ø·)ÁŽ D>ñþÛ\RÏZöËK¹íàÉ"º:P>õÂ|?±üÊ5ÃmátcdhRù’AŒbƒÔX#;þ‚ÁK½º7r:Øcx"cƉ[áã™éªÑ‰ðA£Ew1ôæNñ¡±kϰÇ‘Ð.:Ï2†ËÍ»£–T¿?^éÎ[~hOwL×ßßLjó3á©ï†4È^w³è.—ÃQéüLY»þ4Ã| ‘ÐlŽø,å°ñ¹GÝè( 1–WŒa•“SŽÌõó[JW¦u«&ËJk{ Õ¹ádsq^8g”v²öìÉ!¥™1˜„ŸÓX~Åõáe*áÜ{|ñ-:ÔÁ. ôÆÜ'&Z÷1ŒeÌ©×ûBx.×è?\á:çüx¥5Sã¼{O¤¬ÞºPrIÈdË®è}f "Îëmq®…ìO{D^Dž”Ë,n‹ˆÈ€Ý‡aZ×ïdؽóOzúm³ªx6º£TËÜ•é"AÌÛc=í8HÊ>²:œ‰'Çvs¶às›l4#kÜb 79½äk Ò~~~ñU°ÙÿTÓ,Vî݇ ÆHì¤FË¿Ãñê¸ë0þIßéô5%t‚>´é¼_Ö(üàtH{Aöêóêû>䊣Kx–‘ë϶ˆ8aE*ϦG™Gãö´véY|Ó¤m\Æi›üÜ…v¦º’«ηAky>¸Ø:]íC‡`:w±ëyÚÀÁVMŽÇ2‰‚ñ…ŸõÉìö³Ê%©¡¨}‡Ÿ@¶;Û%b–lñÉAúM[í2Éc6©ÈñÄs¢h£jmN"¦€nQ¿D F oäv?ÙÍWmÖÙ"5—Ö hÏÎä£Li"hö›g î’“óO’ÄB‰\GÛð›°{ YpAß?\óP¡ºl¿RŽår ï ç6 ÙvTŒìõ ›^ãÑPH$‰McT¢ ì5æ©~3Q”¯Kò0 ñŒ¨rv¸C€77 %Ж…GÙÀ("YMýn£}—0Ìß:ßhùÄ9ܘ.ésDåüÂ&ý´Ì„U#‡¿Dúö}üÆ«•AÎØ©³{õTcɾY OâãÏs«Šà,ÆÛ¹—!+ñ­äãä“îRˆ#v øç S#è! ¾Œ"!™ÿÁh endstream endobj 102 0 obj << /Length1 721 /Length2 5243 /Length3 0 /Length 5832 /Filter /FlateDecode >> stream xÚmrPZÐ5ÖâP*P¬+·¢Å‚»-RBB‚§HâRJqw(N‘âîZ¤Å] Å]úñÞûÞûæŸùçÎÜ9»{vîÙs—™^…DƒÝía¼œ¼\<¢ym5^>?3³Œ#Ì G!eÍÑ0Q€> ÐÙxù÷^f€ ÊÞÝne°ZÿNôæP¸Ü ‡B \àÖ€×...R.NÎ\ŽÎ\÷M:0m XÂ0€Œ†¦¡’º€UA] CÂÍMgnP…[ÀN0 Àå@ü,PH(ü/MN\ @ºÀÑ÷Â,Qv59°´¼†: 'à –˜#¡UÅûv$ÚIôž ³p´ûk:ú?„0ÿAþCÿUÝþA\¼¼(Ü €À¬àHî¿|SBZ¢‚ÿ¤¡Îöÿ–î9Ýë°Þ{@a–÷lgBÝÜ`•AÙÙ;£aŽ5æˆh£ìÌ‘ÿ²Ìíà÷ÿ/ïJhó{¤‘V÷Îñü“‚;ÉÃÝ`PM8úÞjKsĽEçõaÿü‹ w¶û§vïÇýBQH„ûÿ>y?Æßrƒõõµ@Êìÿ-Àße9¤ GZtÐ÷^š;BÿKü]Ö4‡ÿ³=ÿŠùw›¼ÿ«™£án€7<\­Ï_ç_dò,åæÉÉ+ü ÀÉÏÇ฿DøÞý?r-œaHô߆ßÏòoü÷"Á`n0 ‚é)”…X€M|͇Bo¹ìÑ¢ì£ÃouÙ§x1 5ï¿!ƒwZCÍÖö¨ŽÀT®D´#~ñ¥ÝE¥£jó(ÑÆÀ`8}°ÉÕE.c‘•wéü•VæeE°éo=J; uœýCtâÌô{M¶Aä´Re‡|q2Þð·õm-Dÿ?A*MX'ÝÁVØKZfý†H^,Oceø/í3SšYgúÙ¯¿b­YœøÆy tdWïz¨Ñg}³.VbC}DJ/aàóÄÑUý˜Ö²R¨ä­çÛÆ+}Õ®‹P[y—W6œƒõJQ G8£[œa°àÑm¡š0 ]V˜ëüøo¹Iã™Y¢k‹ˆ»‚û¾ 6}|ö–nèzÈ#òõMØ ‡H}øôÀì óóëjó]AtŒLé¤KHd_ò,ÅÛò~çáRÉ?‡ö¤ÐÓÀæ«â&³gf¼ N,1Ëö Gbtòw×ãÖÛk#–Òñk´¯¾uã°C´•WKíU*1OšhÍh.Ô;/v~F§plï`í¾JÔ¤0 rþÄ€£8;.ê,¶íˆÀ½ÐW4»™ \vu÷ÞŽ8‹˜ª”}l0æìrû|–Ý5ôUÍ—|>yΓúä«—S©j\Ò]W(Þâ/ë‚hïÇ@x”* (bA,n ô‡Ò£·‰ñJc·oN<îJ]Poc<°~˜­³*öRûÙ­ëúvh.ö­/–ùBy@'±õZLæ™ÉäÞŠo1¯ªá­Œgãìf/**n̶Á‡ƒ¼}ÜBåçâ4Ò}$œ±Ä>…¶Œ:VWR´õÜÉØ´Ÿ™º´@$ºïtÿl=ßàÒmƒ‰0±Òe°]󌭉Nt) ŸoÚ&•éÖÆ´©Å|æÅnÍ!´3i—4m]¡ ©°|)x¢‹µ¯ZBµ°fŠF?aovðœ1ìà ùPÿñH?/°×B3˜<÷S^Œ56Ñt.Ù;.›°zÍlþäÊñ1 Yš?6?NÌäGYöÃBâžý4èçd»ü&d‰Â"k Û¬ÖÁ”XÆkH© Šó]S©FÝå¿Òh6cœˆo)ºç³ˆjš&‰%ú[÷SPïÆn2^h9>«‡g˜•Ë&<˜<îpÞë w¼£ ®2æØ7¯Ë›dÈQJŠq6øè 7­¶JE梕HòÌo:?¦ÓŒcÅÏU|Ÿ®ª5ÔD•w´¯7'Ç£úϨS)÷Ä\Ì E1ÒwZºhR8¥m`׺òVfø7]ͬA"{’^hs[„ëû²A ?‚î7«ý®´À7”z›Ä uÏÈ+Ÿ´ŠÜÕ9Ïîy³m*]~7c|Ùa$ö\¨3¢–îDªQvì31!5¤åÂ!û^QyêJÃÂL~s{EýÀuþÂíÎ,òzÎM~²Òï$ãël¯TäÈügÏ›#ºwEï8ó’ˆNã|1²‡ù©V·ÚÌó&>=7Ïo¢p¯›܉»Ö(òÊŽ´T/(Á ¹ÇQv Óâ•l(yòâ .Ewùrß9_º©¿gR.U£2.Š’û#óõO«t¡7)s—ø¾ÞZC…ƒÂË©/óA3óS¥¯Â¯PþÔ¶L¤Ä/Ø!Æ°Ë ‡TÙþÈÍô/Tóž¬Æ¡-ôrÈ[§½€!+Ô‡e¢6“ÇÕ>oæ”;VBM¬èåé)ßîiÞáñi‘]»f2ÓÀt;}"•ðì4´Ú–ŸÕ¦eîy£)ëXÀÎ’õÁëõ`úlßî+É·¦¿wùç§Ny¸³ů¥\¥žéí©6ßÙ+êò¼7ð q ³5m}¼:é·µw\x‚(gÍ”òuº¾2’ø0F+ o} IØ3Þ(±XâmDY•büˆD&#CLý=â6Áàš×1`u—Nü6?N½A[m¯÷ºïԺإ§¬âD‰†‘-W.]%#¯,¨n{ý@ðvà¨ðÝ£fñþŸ¬øµôïh:öÒÅI¥^ň¢€Zƒ’è\E.Y•;¼¾qA§zèÜ‘CfDØlK×*©á†ì™ðŒ_‹‘¤¥”ëç.Tæ_|'YøiWþœñ0š<«cd‘l’ËïêôTìå™ùƒrœñ-­ ;q—PÏ%ˆ®ÐÓ =’dÙpûf¥†e‡K»;JÌ©‰ä<Â|p7':ý‘BjUõݶÌ^…/ãI$–GÒ6˜ƒ ©Œ¯»LÖ¤?Xa›¬H†”†ü®?O¨å_ç“îúÓë_rHù1*©ÉïÍ1) ¦Nû°y~ÐŽ9à“Gr`nYðÏʨ(~7ýÓoÀ³ìg/¦qÝ.§Ì”0ð‹åð˜„C1†õwžI²qýÑÁW§Ç-×:ƒ¶|Óc‰ŸgÈÈd­Øy› XŸ`ÊÅ}­ÈJE wfpì``Øe“ég“¿tºB@Jg'ø®ì*ëÜDC‰Ô­TNG©—ni7¼>ºy”=}0Ëtxù3sL|t½Ú7#°k•e0ü¥Ë½`¬ü è.Á1Ñ`A›â8hAR$¢£1o'=œZ3ªdT„«Ðì)?µ0ñ©}r÷UcøžÌ %¤sÔåjãõ>·wV"-8¯<>ÿéjPY,õVÉÆ!›}zj.>CbàÂN‰ ¯—˜“¢/ïÙ\ÍcÞ,´ò IÂä2&îiŒOíö\¤-²b ê @œÍU¯üôãÐ:§u+ó—ÿÑ?ÒÆ>ù8ÔW6ÀÇôÑ1Y€ÙNE¬CHC'óÁâà‘VŸ©¶PÝ×r¦È–î”Bgqò_Ý$cÜÍÝFeãìœOî1®4ã‚Q@ëTèUÏÞÒ0ÌÓ}í0Õ¾Oî}¦î•~/¤sù•ÜNÊ5)zJ ûc-I”6cx£?ÂekÂÄÓû+\ŒXyÿ`‚<‡Ï¤>'q¬«$æÕ„Í™ðîÌH÷Ö–ÈÜ¡ïii¨(òÙ3?tOPƒìé¶!†cëÆ®†óªB“ÏùGUê–Q~ð?_ÞDðOAf–ˆkí¬öò»Kò+$¢µYW×À7‘D°§Û6uwNr4qÎͽÌD4u2A]ijÓOŒvóWmš#“@@ªý¬{P/^ IÜÃé®p¬Ôs7¯4À`ì!môdX0òlÓ©iq–Xô[å9mµ©Ûé‹‹=¶ªjáVz¦õC8ì:ïƒÒãîe(óDO1k²|1‡k®‡Ë sRÝÏh<ºœ•»4Õ`4·)7ÂLûhÚäÒHdùR/wRƒš‘+uKÃ6 C•âcõ· ¹fk‰ñ‰À4äe‡ÅÌÜÖ¨ƒ$)R0arØ¥s{ìm+A=ŸQÐïrb{ŸÑ+V?%iýëè5ì+pð}÷ߟ¼æ°bF(2ÄI Õ/_<¢YóÜ÷÷7i ÌN0Ûnëö-3Úïm}áÿÎõV§¤t8(É·Ž®gNefs^¼u€:§ùÇkªLÙçÊ,òÛÚ»ÊÆ^LÙ$LÕÞ/'Gò”`Ü2&õ|„ln=B=µü"“ ©²2?Èõæ,¸M^qS4—}ß¼ÑgW8ÊêÂDß— •TÖy’>t¨ ÒõTŽ{ý“Ó0Jü(@SdòÌ’4á¼¢„k±}µ­ì`®d-Ì?̉ÃO§3XÓPg{eh/ðè·ê»í •¤ÚÓSyº¯-Ç”Tî2Ь!ýùïª@SJ=î³1 ©WŬIxŠ.þɾžÕÜ©·ï‰“Å'%7ú’¹Ù7à\¿ØðEj»2i\->Ö]É o³ý>ha´´ŸHÂÕÄLú58÷¡6ºòuÏ‹bœoƒú>4 ¦³ÓSŽ‚ÎDH¸ï¼ü>ôð%õò­j–-Y Ž ƒ®|ÙÎuQ8'-ØHmšw‹jlÒJI·Õ¡¸\xp<ŠUZúÌÁù’âØl,Œš:Ñ s  µg“Ãÿ4µVð!ÓÎäç„dn˜ú{uw×eÿsüÎëGf»-,@OåYòlYQ{Q-æÁ ¥ro (qZ•™¢ƒ¬ŸXè\¿f¢ü9ha•u›Á£gLÉâÜ$¸ÁÔ ?2*ª*ÿê jܾòˆ˜úøvá…uÀ)áɲšg £·åGI=’"y2Yò#ze…0ì©'!þ…ð^jOåP¢q%1g0Q+` Ý(³ú^«ìÿI »Ù=”Isòʺ BSUDðÖáó–µ kñ­Íã<âÖäÖ|SµéÏc›syßœl#ÐlsJ剮Y \üKiÕƒ«ç ïRÃ侘¹È$E«³U.‹1x££ÝŒm—FÎæ[ALþó唸BèׂCÀyä0aƇZïFó%]‚?¤³<èmCA‹â/L½O5ˆ?‹¥0_–Ÿ$t9`@0)Œ¸ÖCo•ù¡9.¾[œÄ–úÓ±§’|•­òüxs=6ìžt-cÏÕ¸]]!*̤^ö`Å´R+6oòG>f>û44èrã`púeMüYŸÅŒ‰AÎH¼òå9,}÷Ðù-Õá:‚QkƤh÷yîà¹6Aî‹E¯+»Ú†>ÚËP¨&Èׂ Î,6H_8Y­Q^÷Ó/êLÌn¨1ëqb>Ǫij×3#˜«ä¨s¥¦,QPëÈ–)mò‡þd´‹:a3T¸P¾ÉT}ÒÞk%ã™÷UﻥåÁð4?ů:7´ª36WÄ€qŒ­ÔR)vV¯i~Π|²“|T_“Tæ!nAkÈ}¾'`¯Æ'²Wñ& “°/’Ä™ïOŠ€i{Oüdc7±<å·× 'G­¨¿ÉWÍÄs) *fnÈk Ÿ2\šÍëáQœXÊNÄó í‰z«ÁW÷ÞâÜmZÀKX•î”åLG>Å“ô«ÝžcR¨´áëÓi+.|wµeÏÛo‘} Œ‘Ë뵸ÙT|²ðþÓnÍâ|‹@f:ƒºKÐ>ËkÌì±Å& ÅéA¸ö~½ýå^f£}sm¸æ¸V) _„©1‹L/SMw=¼)cH—¨O:IùÝ­Į̂\¶›Ž¼ƒ-å CyAnþ7¿ EüWÇA |§é/œlíŸûTÚ LŸa×)v·§Q§Hµ¯ öÅIúý¶ƒ1ž endstream endobj 104 0 obj << /Length 741 /Filter /FlateDecode >> stream xÚmUMoâ0¼çWx•ÚÅvHB²ó!qØmUªÕ^!1ÝH ¤í¿__‚—m ñóøyÆÌÝ·—ÍDUíÎLÂGÎ^͹½t¥™¤ß·§àî.kËËÑ4ýc*S³ç'öÒµåÆôì>]gë¦î,yÝ”‡KeFÖ×$mÞëÆS°»3¿&åq÷GÈÉîRúº™pßêþ`I_Î3[d·Eæý4ݹn›'&9ç¶7UÚaãL)l:ŠÛ×MÕ zØê!YU—ý0rßåÑžo>ν9®›},—lúj'Ï}÷á4>Óç®2]ݼ³û[ivjs92V+V™½íhýÿØ ›~éñÊyû8&ÝX®²­Ìù´-M·mÞM°ä|Å–E± LSý7—ЊÝ~¤&–Êçø U´ –2´XÆ(p‹m“¡¦ÂÜÂÂ∠ËXXœ(W°8X&˜LR4â=z¨Åu«kTÌGEåïm7hçáË8KÉc`Iu(à!a <#œG´Ž »>ÃÎn-tJ!]O2Çø`œúñãÌSŒóø#§¸­'œâ,<Ø“L€%q¡O8\Ï€™:Žó 3ht ‡,ª+à9­uçgŽCwËpÞDÿ‚|ŽOžRÇɉ#ɇÛW ºmè—’®1NÃwH=8!õ Á éŒ4ôDCp&q"p¢œüBCT/ôŒ9ñ¡!ɨ~Bü }ÒéîRqÒ‰óTÂçFIŸúܨ™ÏŠ|nTìs£Ÿ¥|neEA¼;~æó¤òÛ<©â6OšßæI‹ÏyÒòsžtèó¤g>O:òyұϓN|žôÜçI/|ž´òyÒÚçI§>O:óyҹϓ.|žRîó” Ÿ§Tú<¥³ë¹_¾û¥ãmÂKz}öÊK×ÙÑ=·î¡ÃW7æú"ŸÚV¹{ÊÇÿŒž‹à/znªb endstream endobj 105 0 obj << /Length 711 /Filter /FlateDecode >> stream xÚmTMoâ0½çWx•ÚÅvHU„dçCâ°mUªÕ^!1ÝH $úï×3C õz¿¿Ì¼Ìï÷íÌÔÝÞÍÂg)>ÜÐ]úÊͲ߻sððwÕåäÚñÕ¹ÚÕÓéð"Þû®ÚºQé;4mÝ_%‰= ”uS×'ü¯N¾%¼ýFwÚ´‡.HS1ÿð‡Ãأʧ`þÖ×®oÚ/ñx§ÍŸm/çóÑ!ƒõZÔîàKú¼îNNÌ~Íéóûì„ÆgEʪ®vÃyW¹~×~¹ •r-Ò²\®­ïÎbÊØ&jâ©r ¡‰ÖAªCu é±Àad)°ôXyœ x¤ &äI)RÌêVÔ˘.L¢I@õo×_¥Êpi k-cÀšâp¡ [À Âàˆn€cÂXçz3æ‚N­4Ö´ˆW Yf„‘ŸÓË%€ Ä9%bë™*Ô©Bˆ+Ðé›|¥© A…Ä_F:CêÔ9èQÔYƒ5ŠÀKÊEê—9r¨ÏèW8f•a¼D>éÏSG&ýx¯VôŽ _kU8!¼ò8ºŽ0L5#àD½ ÔJÒ üXê'9ÅŸ?‡: iÀYI WFñÜæ¹›çn endstream endobj 106 0 obj << /Length 696 /Filter /FlateDecode >> stream xÚmTMoâ0½çWx•ÚÅ$ !Ù ‘8l[•jµWHL7IP‡þûõ¬V=Mžß̼ñ s÷ëu;ÑU··õÈÙ›=w—¾´“ì÷îÝÝå]yil;<[[Ùj<=?±×¾+·v`÷Ù&ß´õðàÈ›¶<^*;²~&ûQ·‚>ìþÝþ”MS 9Ù_êãP·ò{=éÇsæ@öd”ôÇöçºkŸ˜xäœ;`ÝVY×`Œs4½JaÓQÜ¡n«þª‡í¡.’Uu9\ßèY6î>¼ý<¶Ù´‡.Z.ÙôÍž‡þ“4>DÓ—¾²}Ý~°û¯ÒÜÑör:-d0­V¬²WÑÍÿ¼k,›þ8ãóþy²LÒ»ðºÊ®²çÓ®´ý®ý°Ñ’ó[Å*²mõíLrŸ²?ŒÜÔqù¥ã• â5F8@ šˆ=@Šð)&°  È8Ô¹€ÂÅRx u€Dº\j2H—†ª¡ÐVÁ¹0CzL]ø Âb°ct‘I ©g$`htÑ‹0œÆ\F„áŒ0ä†sê‡á jd< —Iê6œ»õñzgóñºË»þê W ¤qÈ’£+—Ÿ#ö•ñÌÇkÄÞ .‰bªsré…¤šáæÄç†bïmŽXú¾„Kß7ǵHß7Géû„û¾nb§>&jÊØµäuœ¯¼ú•ñ1ÜV™÷•âÜãâµÇ‰Ou$ÕŸqWèS/%1{\øxB!€§ÔK(hH©—TЖ枃»J©Ïϯv×ÜëÁ=küÒ2ø¥UðKÏ‚_:~é$ø¥Óà—ÖÁ/¿Œ ~™Eð+7¿èË¢/ ÿlì¡ÛÒ(/}ïö -+ZXukoûìÔE?Z„ãæÅÛKý£ûƒÎ endstream endobj 107 0 obj << /Length 739 /Filter /FlateDecode >> stream xÚmUMoâ0¼çWx•ÚÅvHU„dçCâ°mUªÕ^!1ÝH ý÷ëñ#xÙö?ŸgìÁÜýx]OTÝmÍ$|äìÍœºs_™Iöss îîò®:L;<S›zœ==±×¾«Öf`÷Ù*_µÍð`É«¶ÚŸk3²¾'ióÑ´ž‚}Øý»ù=©½à“í¹ÙM;áà¾7ÃÞr¾›f¶ÆnjÌ-ùeúSÓµOLg~¼À8÷ã ãâþÈ)okà çA„8 ö$`I\èÎ×3`çAfŽã<ÈZ]ƒÂ!‹„ê xNkÇyã¹ãÐð"œ7Á¿ _¥ã“§Ìq âH`òáö•‚nú¥¤kÌÂðRONH=CpB:# =Ñ%8“ˆ88QA~¡!*ÉzÆœøÐäT?!~Ž> étw©8éÄy*ás£¤Ï }nÔÌçFE>7*ö¹Q‰ÏR>7в¢ G]¼;~îó¤ŠÛ<©ò6OšßæI‹¯yÒòkžtèó¤g>O:òyұϓN|žôÜçI/|ž´òyÒÚçIg>O:÷yÒ…Ï“.}ž2îó” Ÿ§Lú> stream xÚmUMoâ0¼çWx•ÚÅvHU„dçCâ°mUªÕ^!1ÝH ý÷ëñ#xÙö?ŸgìÁÜýx]OTÝmÍ$|äìÍœºs_™Iöss îîò®:L;<S›zœ==±×¾«Öf`÷Ù*_µÍð`É«¶ÚŸk3²¾'ióÑ´ž‚}Øý»ù=©½“í¹ÙM;áà¾7ÃÞr¾›f¶ÆnjÌ-ùeúSÓµOLg~¼À8÷ã ãâþÈ)okà çA„8 ö$`I\èÎ×3`çAfŽã<ÈZ]ƒÂ!‹„ê xNkÇyã¹ãÐð"œ7Á¿ _¥ã“§Ìq âH`òáö•‚nú¥¤kÌÂðRONH=CpB:# =Ñ%8“ˆ88QA~¡!*ÉzÆœøÐäT?!~Ž> étw©8éÄy*ás£¤Ï }nÔÌçFE>7*ö¹Q‰ÏR>7в¢ G]¼;~îó¤ŠÛ<©ò6OšßæI‹¯yÒòkžtèó¤g>O:òyұϓN|žôÜçI/|ž´òyÒÚçIg>O:÷yÒ…Ï“.}ž2îó” Ÿ§Lú> stream xÚmUMoâ0¼çWx•ÚÅvH U„dçCâ°mUªÕ^!1ÝHDI8ô߯Ÿá-Û@ãçñóŒ=˜»¯Û™®Ú½…œ½Ù¡=÷¥¥?w]pw—µåùd›ñÙÚÊVÓìðÄ^û¶Üڑݧ›lÓÔãƒ#ošòx®ìÄúždìGÝöa÷ïö÷¬<õBÍöçú8ÖÍŒ÷½ŽóÝ4s5vSc~É/ÛuÛ<1ñÈ9w…¼©Òö†`~ÑÁ擲CÝTýE Ûƒ´@HVÕåxùïòäo?‡Ñž6Í¡ ’„ÍßÜä0öŸ^áC0é+Û×Í»¿Qæf¶ç®;ZPÁx°^³Ê\Cçýyw²lþÁ+åý³³Lú±@Ue[Ù¡Û•¶ß56H8_³¤(Ömªÿæ®Ø&ªrT¾„¯PGë ‘¡Ã2†wØ`24XXºBX8aÁá ‰…ÃJû‚ÃA¢`R¥Ðˆ è¡¡‡^]wqº&j9)*ÿìú‹v®`‡ÆRò°Ä:(à!bx8ápŒØ÷¹ììׂN)¤ï‰&â>0Ni¼‚qFãÆù?ü‰SÜÖ€'¼ÂYðàNR–È}Â{àfØ{©çx2­¯AÃ! …u x‰k=Ç{ã™çàäàExo"ÿ}žžRÏÉ‘#£¿¯xÛ _J¼Æ °B ¾Cì©bÏ8!ž‘=Ñ%p&r"àD9ú Q¾ gÌ‘T†uà+ägÐG¡N—š£N8O-(7ZRntH¹Ñ ÊŽ(7:¦ÜhE¹Ñšr£1+ôè‹wÏÏ(O:¿Í“.nódømžŒøš'#¿æÉ„”'³ <™ˆòdbÊ“Q”'³¤<™åÉhÊ“1”'“RžLFy29åÉ”§”SžRAyJ%å)]\ïÌÿòý/Þ&xG¯¯^yî{÷ úÇÖ?tðÄÕ½¾Ç]ÛÁ*ÿñùô·£—"ø »s¨s endstream endobj 110 0 obj << /Length 740 /Filter /FlateDecode >> stream xÚmUMoâ0¼çWx•ÚÅvH U„dçCâ°ÛªT«½Bbº‘ ‰B8ô߯ß{ .Û@ãçñóŒ=˜»/Û™®Ú½…œ½Ús{éK;Kîºàî.kËËÉ6Ã/k+[M³ç'öÒ·åÖì>Ýd›¦yÓ”ÇKe'Ö÷$cßëÆS`vÿfÿÌÊS¯fûK}êfÆúVGGùf–¹û\b¸à·íÏuÛ<1ñÈ9w…¼©ÒöÎÁ|Á擬CÝTý¨„íAW $«êrGø]žÜIÀâíÇy°§Mshƒ$aóW7yúÔ÷ÌŸûÊöuóÎî? sÛK×-ˆ`ãθtJ!±'™ˆcøÀ8õãŒ3?NaœâOœâ¶<Dg!Àƒ;IXô ôÀÍ0z)rЃÌ@« kÐpÈBQ]^ÒZä 7ž!‡î /½‰ü òU Ÿ<¥Èɉ#“ÜW ºmÐ/%]cXß!õÔÀ ©gœÎÈ€žhŒœIDœ8QN~ACT/ès⃕QøŠøôQ¤ïRsÒ ç©…Ï–>7:ô¹Ñ ŸùÜèØçF+Ÿ­}n4eEƒ=zG~æó¤óÛ<éâ6O†ßæÉˆ¯y2òkžLèód>O&òy2±Ï“Q>OféódV>OFû<ãódRŸ'“ù<™ÜçÉ>O)÷yJ…ÏS*}žÒÅõÎð—¿tx›à½>zå¥ïÝ{ˆO->tðÄÕ½¾Æ]ÛÁ*üà3>ýcÀè¹þ¤C§~ endstream endobj 111 0 obj << /Length 739 /Filter /FlateDecode >> stream xÚmUMoâ0¼çWx•ÚÅvHU„dçCâ°ÛªT«½Bbº‘ A!úï×ãGpÙö?ŸgìÁÜýxYOTÝmÍ$|äìÕœºs_™Iöss îîò®:L;ü2¦6õ8{zb/}W­ÍÀî³U¾j›áÁ’Wmµ?×fd}OÒæ½i=û°û7ógRúùd{nöCÓN8¨oͰ·”of™-±Ï%æü6ý©éÚ'&9ç¶P´uÖ`àL/"Øt”µkÚº¿(a[è „duS —‘û®ö$°xýqÌaÕîº MÙôÕNž†þÃé{¦Ï}mú¦}g÷Ÿ…Ù‰õùx܈` étw©8éÄy*ás£¤Ï }nÔÌçFE>7*ö¹Q‰ÏR>7в¢ G]¼;~îó¤ŠÛ<©ò6OšßæI‹¯yÒòkžtèó¤g>O:òyұϓN|žôÜçI/|ž´òyÒÚçIg>O:÷yÒ…Ï“.}ž2îó” Ÿ§Lú> stream xÚmUMoÛ:¼ëW°‡éÁ5?$R. ¤d9ôMðð®ŽÄä ˆeC¶ù÷³k›m‘CŒÕp¹;;†wŸ~>Î|¿Ž3óEŠ_ñ¸?O]œ5ß¶‡âî®Ýwç]Oßcìc]=~?§}÷Oâ¾yhÆáô9%?ŒÝ۹׬“B|Æœ‚>âþ)þ;ëvÇw%gÏçáí4Œ3‰ä§áô–’>\ ‚‚6ý§ã°¿ õEJ™€õØ7ûÆ8ó 1¿’{Æ~ºðÏ`W(-ú¡;]¾è·Û%=°ùñýxŠ»‡ñe_,—bþ+-OÓ;qü\ÌL}œ†ñUÜÿI--=ž‡·B«•èãKª˜æÿ¾ÝE1ÿpÆ[ÎÓû! Mߊyuû>Û.NÛñ5K)Wb¹Ù¬Š8ö­iÇ[ž_®¹uÊ•MúÑzQ­Š¥Ò)V†€Ú(TØ€àx¿àÞ¢ žjy‹°°!ÀÐÔ•µZÔÀ2àP="¦ZdÔ0\ÃG©R\¡·”).–2*ÎШa!„U¼Ä,†³ÔÛHð° `+jÐÃ.¸5Nα@èâ°èÐVK-àxŸ%ô˜Ü3š% A°YÓ€z¡ÎšÔ>kP#¬³¦õ™5m0W£oš¦Ã¾žj­®§Üý·.†ÐZ¡ŽT$X/©)n)æ#W—„o(æ“oÀRZÞ $K¢p4’ŽZ¶-bâ\­1¦Ü°Jä æP"Gñ‘XÔQ¬‚i/8ºkÉ^€ÂZqŒ:ZsŒ½š9”d š­Bù Ž)ßsLù-ï7½æx˜ÏJ›¡¾Ò`¯ažÉ½)f¥É$†µ’1™¸ dÑŠcªCZCù<£7Ã3JÊgózÌnøþHȰíáÌYÉšäTœ¯a…Šï¯Æ,_»œ-Ÿ—Oë87Ë}êÛKÔ´Ü—Ll¹oKñšò+Êg­JÌâ.¾GZyóº‹Vðc­48¸’ï¼äØWtù]Í:P~`áŒñ±–rZŽq.nÍ1]Ç ÇàSÿæ/©ßP•ýïuö¿7Ùÿ¾Ìþ÷Uö¿·ÙÿÞeÿû:û?Èìÿ ²ÿƒÎþ&û?”Ùÿ!dÿ‡&û¿1y–¦¼ÍH·œn5þ¹ã)º½ÝyšÒ“Bï½x#†1Þž´Ãþ€]ôGoáõñÅ×Mñ?®Xê endstream endobj 113 0 obj << /Length 750 /Filter /FlateDecode >> stream xÚmUMoâ0½çWx•ÚÅ$*B²ó!qض*Õj¯˜n$H¢$úï×3Cð²íh<~3~Ï~î~¼ngºj÷v¦9{³C{îK;Kîºàî.kËóÉ6ã³µ•­¦Ýችöm¹µ#»O7Ù¦©ÇÞ4åñ\Ù õ=ÈØºñ8‡Ý¿Ûß³ò4Ö‚Ïöçú8ÖÍŒø½ôí>sIv›dXôËöCÝ6OL xû9Œö´im$lþæ6‡±ÿDŽÁü¥¯l_7ìþ–šÛÚž»îhãÁzÍ*{pþçÝɲù·¯˜÷ÏÎ2‰kA¼Ê¶²C·+m¿k>lp¾fIQ¬ÛTÿíÅT±?LÐØAù>J‡ë ‘¡‹e .1›ÊPbéªpqH I$\kL¸8HbØŒShÄ…r =ôêzŠã51Xò‰Qùg×_¸sµ‚2¥äÄ’òÀ€+Š Ä ŠsˆC:CQŒ}.'c-ð”BbOEðƒuê×+Xg~Â:ÿ?aŠÛàj îB€.U ±$,ð¨›ĨA¦ˆA 2®‚žAÃ%‹˜òâ%Õ"µñ 1ô9h¨M„ _®ñ¤)ELN 1éÀs¥ ×þRÒ3fg =傸aîCÑYj¥ VÑÝà^¬w&L˜Ó=·° ½Ð3â„nqFyÀDŽϠOLüñ5'žpÏZx?iéý¤•÷“^x?éÐûIGÞO:ö~ÒÚûI“‡4ðÑíˆÏ¼Ït~ë3]ÜúÌð[ŸñÕgF~õ™QÞgfá}fBï3yŸ™ØûÌ,½ÏÌÊûÌhï3c¼ÏLê}f2ï3“{Ÿ™Âû,åÞg©ð>K¥÷Yº¸¾Nœ0³`Â^Çayî{7)q ã„ÑW7ö:©»¶ƒ*üሟþS`õRé̯ endstream endobj 114 0 obj << /Length 750 /Filter /FlateDecode >> stream xÚmUMoâ0½çWx•ÚÅ$*B²ó!qض*Õj¯˜n$H¢$úï×3Cð²íh<~3~Ï~î~¼ngºj÷v¦9{³C{îK;Kîºàî.kËóÉ6ã³µ•­¦Ýችöm¹µ#»O7Ù¦©ÇÞ4åñ\Ù õ=ÈØºñ8‡Ý¿Ûß³ò4ÖBÎöçú8ÖÍŒø½ôí>sIv›dXôËöCÝ6OL xû9Œö´im$lþæ6‡±ÿDŽÁü¥¯l_7ìþ–šÛÚž»îhãÁzÍ*{pþçÝɲù·¯˜÷ÏÎ2‰kA¼Ê¶²C·+m¿k>lp¾fIQ¬ÛTÿíÅT±?LÐØAù>J‡ë ‘¡‹e .1›ÊPbéªpqH I$\kL¸8HbØŒShÄ…r =ôêzŠã51Xò‰Qùg×_¸sµ‚2¥äÄ’òÀ€+Š Ä ŠsˆC:CQŒ}.'c-ð”BbOEðƒuê×+Xg~Â:ÿ?aŠÛàj îB€.U ±$,ð¨›ĨA¦ˆA 2®‚žAÃ%‹˜òâ%Õ"µñ 1ô9h¨M„ _®ñ¤)ELN 1éÀs¥ ×þRÒ3fg =傸aîCÑYj¥ VÑÝà^¬w&L˜Ó=·° ½Ð3â„nqFyÀDŽϠOLüñ5'žpÏZx?iéý¤•÷“^x?éÐûIGÞO:ö~ÒÚûI“‡4ðÑíˆÏ¼Ït~ë3]ÜúÌð[ŸñÕgF~õ™QÞgfá}fBï3yŸ™ØûÌ,½ÏÌÊûÌhï3c¼ÏLê}f2ï3“{Ÿ™Âû,åÞg©ð>K¥÷Yº¸¾Nœ0³`Â^Çayî{7)q ã„ÑW7ö:©»¶ƒ*üሟþS`õR$m¯ endstream endobj 115 0 obj << /Length 672 /Filter /FlateDecode >> stream xÚmTÁn£0½óÞC¥öÆ6’*ŠdrضjªÕ^pºH‰A@ýûõŒCf»êô¿™yã'æîÇën¦êö`gñ#govh/}egæç¾‹îîò¶ºœ­Ÿ­­m=Oìµo«Ù½Ùæ[׌ž¼uÕéRÛ‰õ=IÛÆú°ûwû{VÇQðÙáÒœÆÆÍ8ß›ñäIßž3d_ƒ “~Ù~hZ÷ÄÄ#çÜ W›ö c Ñü*…Í'qÇÆÕýU;€ºHHV7ÕxýÂwuö÷É»Ïa´ç­;¶ÑzÍæoþpûOÔøÍ_úÚöû`÷_¥ù£Ý¥ëNd0m6¬¶G_ÑÏÿ¼?[6ÿvÆçý³³Lâ·ºª¶¶C·¯l¿w6Zs¾aë²ÜDÖÕÿ%!ãpœ¨™§ò%¼b•l¢µËÜc€Ã¤ ¥¤ÀÈ ¤ÀPÀP«[ ßuªŸñ©_õgß_•ñxû4Ž$Oˇú<X^\NB8 ë\;c®‚šBbMx¹ ùy˜%ÆPÈ 3jok:E q:¹Œ/d4ˆ8ð€Q§4ÈA2="\¤ÂšYˆ+ÀË‹ÔÏsä(Äè5$ YŒ—Èú rŠÀ‘€ƒ~ì+A¿\HÈ•ÐWr߯{ÇNøxoËøŠ‡û• ¿”$¿TL~©ù¥òK¥ä—ÊÈ/¥È/¥ƒ†p˜1ðsòQä£*ÉGÍÉG-ÈG-ÉG“zA>ê„|Ô)ù¨3òQ/ÉG½"µ"µ&µ!uN>ê‚|Ô%ùh8ùhùh$ùhbòÅ,n~á†üá°nË£ºô½ß+¸´p]À¢hœ½íµ®í \ˆÓ†¯—2ú ¯M„Ç endstream endobj 116 0 obj << /Length 672 /Filter /FlateDecode >> stream xÚmTÁn£0½óÞC¥öÆ6’*ŠdrضjªÕ^pºH‰A@ýûõŒCf»êô¿™yã'æîÇën¦êö`gñ#govh/}egæç¾‹îîò¶ºœ­Ÿ­­m=Oìµo«Ù½Ùæ[׌ž¼uÕéRÛ‰õ=IÛÆú°ûwû{VÇQÈÙáÒœÆÆÍ8ß›ñäIßž3d_ƒ “~Ù~hZ÷ÄÄ#çÜ W›ö c Ñü*…Í'qÇÆÕýU;€ºHHV7ÕxýÂwuö÷É»Ïa´ç­;¶ÑzÍæoþpûOÔøÍ_úÚöû`÷_¥ù£Ý¥ëNd0m6¬¶G_ÑÏÿ¼?[6ÿvÆçý³³Lâ·ºª¶¶C·¯l¿w6Zs¾aë²ÜDÖÕÿ%!ãpœ¨™§ò%¼b•l¢µËÜc€Ã¤ ¥¤ÀÈ ¤ÀPÀP«[ ßuªŸñ©_õgß_•ñxû4Ž$Oˇú<X^\NB8 ë\;c®‚šBbMx¹ ùy˜%ÆPÈ 3jok:E q:¹Œ/d4ˆ8ð€Q§4ÈA2="\¤ÂšYˆ+ÀË‹ÔÏsä(Äè5$ YŒ—Èú rŠÀ‘€ƒ~ì+A¿\HÈ•ÐWr߯{ÇNøxoËøŠ‡û• ¿”$¿TL~©ù¥òK¥ä—ÊÈ/¥È/¥ƒ†p˜1ðsòQä£*ÉGÍÉG-ÈG-ÉG“zA>ê„|Ô)ù¨3òQ/ÉG½"µ"µ&µ!uN>ê‚|Ô%ùh8ùhùh$ùhbòÅ,n~á†üá°nË£ºô½ß+¸´p]À¢hœ½íµ®í \ˆÓ†¯—2ú á«„Ñ endstream endobj 117 0 obj << /Length 720 /Filter /FlateDecode >> stream xÚ}TMo£0½ó+¼‡JíÆ6„˜*ŠÄ§”öUS­öš‚ÓEj9ôß¯ß IV«ªÐcüfüæÙÌÍçŸÔÝ›õƒ{)^ìØ†ÊúÙÏ}ïÝÜä]u:Úvz´¶¶õyu|ÏCWíì$n³m¾m›éΑ·mõqªí™õ5)µïM{¥`qûjûS5•–Ò¯ŽþxêíàO£ò%r^›éÃq¿£ ·&¾\Tâ—Ʀk„º—Rº@ÑÖYwDo£·˜õ‰ÅYñ¡iëa)Þ ÙSZÔM5Í_ô®ŽÎ$$ï>ÇÉ·í¡óÖk±xq‹ã4|’â;oñ4ÔvhÚwqû¥BÇØúþÃBÞf#j{p…7û£‹ï¿P_?{+4}+VYuµû}e‡}ûn½µ”±.ËgÛú¿µg¼fjj»—”{k:l–F #Q—hJqØ ‡Ó HQ/e†Ã.!Pp #]gQtVTýÙ³v)#l-g„À!×7À'užÓ¾:[sI œr.ñ3æ§À9u¢‡•f Í*‚gQNxEq—æ°V1ô¨˜1šVå•£¡Y‡qÍ:54köDC›†Z+ÂÇ)—]ÑØWs͹8:а/È9õƒ‚ãÐR\Qýr—z\®8Ç€û]按Sp/ ¸d8ýãDœ(B®‘ì!ü4êê¹Ñ׳0û«„30û †=å;føz¡ÞJìm’«w&½^0C~±ï†Ï/nS0†G†½K°WÌçš Nò¾Ð³žýdzG¨³ž5c¾C)Õ!=E€^â”øÔK<ûŽ3‹Iò 8ûÈ¿ Ÿq‚3N˜OgŸÎ{ACšò¹ÂßtÖ~Qn~ɸ\Í ý%ø¯1“.“£: ƒ*4¸hH`<4­½Ì¶¾ë‘E ÅóhÆ×Séý!|Œ¼ endstream endobj 120 0 obj << /Producer (pdfTeX-1.40.24) /Creator (TeX) /CreationDate (D:20220607151824-06'00') /ModDate (D:20220607151824-06'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) kpathsea version 6.3.4) >> endobj 9 0 obj << /Type /ObjStm /N 76 /First 614 /Length 3480 /Filter /FlateDecode >> stream xÚí[[SÛÈ~÷¯Ðã9µæ~«JmU !—]6,…T*âcÛd³ûëÏ×=²%K08§ÎÃVEãѨ§çëËt÷E²PEB£ C¡T¡C*”/LÀ+¬Ç]*œÇ],¼K…6Ep¡Ðºˆ6õt,’—˜T(étaX˜Tâˆã e4îm¡¬Æ}Sð3 ÷XÌ‚>`Ü‚>*Ó³ ‹)Ö`Õ¤ < ÄKhðqëK[8ƒßä Âã°˜‹…ö€ä ¿–…ccÏ@·Xô)…ç¿ÚË`ácaæ°’ÁKˈ{ Ñ/‚)¼ º‡GÞÒH$~a}è,x,U"˜ESDZ/:tA ÕÆ\1AÙ ¢%íB/™"Y€Lj„ªS(ÉJ*H—‰‘Z\ "“(ecAöRXÅ’Ò¡B mcÜõðLav*<~ ßDæÄ-¡-‹'*†ÚÈR˜ì¨ƒÉP8:4Ùb -¸é¤|Oa!#=!"³bª&cÈAÀØ@•X'RœÃÊ8zOŸöÄÑ_We!öûeOìŒG³r4›îwÐåt|=9+§ðEØ+Ïýíñ÷âƒÄ€‡s†¤?ö0}‚y´<‘ýü3sÞ·âéÓBìÂá,=¡.šwaÞy—t–»8r\Äþd|vXΊ@ø|·Gå÷Yñq¾ÀÐUûÆÀ/°­ØG¡ôncèàî”äèµì ?V÷ˆGZm ½m£GàÙ”Û7 ׂ4Ñcãëùΰ¼ý#JêˆþW†x d£Û¼dcîÖ~c‡6æ£<½ï ·C£ïÜ(ÓCÑwÜÅ„‹þÆ}ÛÜ”Äv¼Èþ/Ú çX×Al6…øî|Õ @–ŠÜG…`ç4êvÎÕ„M‘Öuìãä”ö¡0;Fq÷3Š 0Ê= á¹.|„„¾“ª]ܘ„›*4>xe¶ $Õ[(•cØBÕjöd·,„Gß~ªÔ–ZÙF£ÀÇ’Ö Í Êmùª­(¢÷„2çPhGÏò NÑjQÑúÁ'¢®ú¼>ÓX·RÕfŽÍ§ÆýœÛmHïÓV<m^«I“G‚%ýi€ª’®íCĨw$1Ž4Êt&²>4é€äð:@³1581×<¿ZA'è&[¨Z!Sr›ñiŽd‹6õÚÔJS¦S€?wfæ«å65çd²–Í´°Sߺ|ÍûFÖ÷s:º×¸"ïíZVž ;CÏDYåõWh“gò^FnõÅ?í?í­-íÈ€èÊžEÕÒãÚ̧j-Åî¼Â÷ÑRä)Q>cÚˆÙ¦Ú»ArÕ‰˜BÔé=v¤"™GT¤·ðžD¤ÐÄE««úÑP*¢ü"‡_o™Ž¦7ðU7·'‹…°NSM‰œå]N{OÊü›«YË9éit.?&Чy$™PQÔ´ù¹u„ÃZî×Tü,k(÷¹¥Ýó-NŠtEåùâ|•8Âßš×(cYãtYãÍÌ9‡§¤o9·Òju¯¦hfœf¾ägˆ‘vCùyަ‘=™9·y„¤ôÉ,<*X.ï8ãz“ÝÅ0å&h“þlÄ¹Šª9è=ñ,3ç—gV¼5‰¤ûŠ7QÑßÒ¤ô‹—â’À˽úŽØdsÔ½¦i´6-‘ïIõËJF ö¸6ói¶A%^S·y„LD‡QÚî{šÜ‘‹AMe •=ŠÓ«©(&‹ 9@²@Ï“ÕóŠ+Ï®ú‘Ê2ÇEO^¡Z“Ûä¨xiŽPÁ£Š¦&ºýæHæl%¹w³¯¨âM57ó¹¤ÒMÐ|2á¹MžLC¥/ýÅ–dÍ}~ k%.ò#Ÿh"#‚岌ûTBäƒIˆž_Z˜µRÒåZu1ä=/UÊG§n?·Õ[™ˆÊ$)³ù4ÃU½¡ÕéjqÖçCÓx“߸ä÷ü.ûÕ8sÈ}®w?6Þ_Ñ›¦çåôl2¸š'ùÍÓoýKQ†ý‹ia3Å6¿ÈzâLñD»êoà(ë>öijé½Îò ”;ý«Wåàâ3n£ï Z†ž=Qôðõ¬?œ=] ËBöÄᬼüƒþàÛ'Õ$œàÀãsBo±þ%ž‰m±#^ˆ]ñZü*öÄoâ­8‡âHü!ŽE_œŠ3q.JÁ“Å'ñið­ŸÆ×q!>ÿuõ¹‰øŠK1c1•âJ\•“Áø\|1Óòˆ¦ƒïb&fŸ'e)fŽÅµø&þßÅ_ÿβï€8øæëº»T¹spøf÷T¹s¸£äºÄ©á‰æp˪DA±¬JS«R®ÐcÐ 5ÕTã+ëJL–ĉëˆs´¿²¿ qö^¯ò £æâh‡g˜Û<ã Ÿeòn¥LgãË˾(¯¦ƒáx¤`æÊ¬³¦ŒQ®#㫃7ïž?ƒŒ+ öÄʹˆ2=FÄ…Ñ|Z) ù~íùoÙëO*ŸÏ“ç“Ï“³Cs/_x8ù÷¬òå%OŽzµìî¿Ú>~ÁjYey›c‚èf´ânÕÊŽxΚy)^A;o‘a¿Š ï8:Ôº‚ƒ44–cE9:ïO?‹òëuHJd=æð1\Df ùRéw4@Y„z‘?,?Íro¬+í_ ¯§2_¯Ç³2?ÈñærÕ‘g:$(7Æñ·ø»œŒ—Œg×1ÞÉë·Ï¶ß±ñ ã™ìÓÉÒ ’toã¹Æs¦i<Ù4ÞK6 aPÇãÚW¯—Ä\+Úî¾ùbŸÅ\!¥ÕÎUZoÄGÃêKbÁŠKÒ¬l÷OÞ¾zq@ÒÄ6ó‹Ì!7#_Gš´VX=yþæxwÒ¾_Wu*žÐ7vJш޾ÌåpKV®”è´¿”ÓZÑðèýÁþÁ ¤9z½Jã¾f7•ãJi¨>ÚCœ+)ˆ (þSà™ ž|[’r­°ñúðè×ãí,¥¾Í©¤ÓÞf¤4·ÄýÎuÍ÷©¡ëü×L|­".­Vþxÿîå3ª‡ŽV–Ђ¡W2(À“o(A©%%ÐíB Zëõ ‚ç\üæôU‰M¹¢ÒZ¡æxïd{çM–p…¡©¬£38}KšÜã%¼orÝHì¿/R;U²ýKdit.úSJ®Ó/¢?ƒcœöϾädz:韕œ˜¹—ó/u¿”³Å0úùA»H8‡ýI]+Ì‹„\\LÊ>Ví–Ãr:­k„Ñõå)P.Fw– ¤²›Ê†óÓáCë‡ëÑ9?OÊ[J ”±k…¾ããß·ßüt¸{°§´\±TDô3ZÒÇÐTTèÚa–"¹¼ûDãäÊJâôz8,g˲ÜÆ_ŒÎÆçƒÑÖ|úTBçôyÆe|ÅácWv¬~}:ã[„ƒn÷§%Ñ9/©Š¾”æÏ>v“錰¾þk¿ºQ¼Žç³ÏSúèšIÆïF°ç9á_ oÃÓ9d¶¥6 š€(òι. ·> ö1qOTm ] /Length 349 /Filter /FlateDecode >> stream xÚ%ÒÉ+`ð÷ùcl3vÆ>ö}û6vÆ‘r¹:埛“£ƒ“”‹RŠÔˆRÊ25%J‰Ô”øžw.¿žç}ë=|}""FÄ"q S/$¤‡ŒÃ|9t;IÄ@œS:› ñ$â¹Ò™“$@¼ZG‰‹$B*^tÖG†I2I‚ÔŠ.RI Ä¿¨uЏI$;ŸN<`ÖL’™{ÒšM² +Zdˆô“1’Kr K±ù$²²¬u„L“â…¬†uQHŠH1)!¥¤ŒøH9é&¤’T‘jRCj!ëz¯r´¯©rÒÔù>ÖÔøcOÜìD45ÏšZ€³Øk´§šÚ€è¦vß¼&?Ìlº¦˜Í=M0‡Éšº`΃s±m¹Üµ\ï[B·–;û-Ìý åaÍòx` oY"'–רåýÍòñ §‚dæóWà0.ùŒDA endstream endobj startxref 197129 %%EOF mwrap-1.1.1/src/000077500000000000000000000000001430266125200134305ustar00rootroot00000000000000mwrap-1.1.1/src/Makefile000066400000000000000000000020561430266125200150730ustar00rootroot00000000000000include ../make.inc # === Primary targets === ../mwrap: mwrap.o lex.yy.o mwrap-ast.o mwrap-typecheck.o \ mwrap-mgen.o mwrap-cgen.o mwrap-ast.h $(CXX) -o ../mwrap mwrap.o mwrap-ast.o \ mwrap-typecheck.o mwrap-mgen.o mwrap-cgen.o \ lex.yy.o mwrap.o: mwrap.cc lex.yy.c mwrap-ast.h $(CXX) -c mwrap.cc mwrap.cc: mwrap.y $(BISON) -d -v mwrap.y -o mwrap.cc lex.yy.o: lex.yy.c $(CC) -c lex.yy.c lex.yy.c: mwrap.l $(FLEX) mwrap.l mwrap-ast.o: mwrap-ast.cc mwrap-ast.h $(CXX) -c -g mwrap-ast.cc mwrap-typecheck.o: mwrap-typecheck.cc mwrap-ast.h $(CXX) -c -g mwrap-typecheck.cc mwrap-cgen.o: mwrap-cgen.cc mwrap-ast.h mwrap-support.h $(CXX) -c -g mwrap-cgen.cc mwrap-mgen.o: mwrap-mgen.cc mwrap-ast.h $(CXX) -c -g mwrap-mgen.cc mwrap-support.h: mwrap-support.c stringify ./stringify mex_header < mwrap-support.c > mwrap-support.h stringify: stringify.c $(CC) -o stringify stringify.c # === Clean-up targets === clean: rm -f mwrap.output rm -f *.o *~ rm -f stringify realclean: clean rm -f lex.yy.c mwrap.cc mwrap.hh mwrap-support.h mwrap.pdf mwrap-1.1.1/src/mwrap-ast.cc000066400000000000000000000205211430266125200156520ustar00rootroot00000000000000/* * mwrap-ast.cc * Recursive routines for AST printing, identifier construction, * and destruction. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include #include #include #include #include "mwrap-ast.h" /* -- Add inheritance relationship -- */ /* * We represent inheritance relationships as a list of child classes * associated with each parent. This makes sense when we generate the * type casting routines, since we only allow casts to the parent * types. But it's the opposite of how inheritance relations are * specified syntactically. */ map class_decls; void add_inherits(const char* childname, InheritsDecl* ilist) { for (; ilist; ilist = ilist->next) { InheritsDecl*& children = class_decls[ilist->name]; children = new InheritsDecl(mwrap_strdup(childname), children); } } /* -- Add scalar type data -- */ /* * The names of the numeric scalar types are stored in the set scalar_decls. * We provide a basic list, but the user can specify more -- the only real * constraint is there has to be a meaningful typecast to/from a double. */ set scalar_decls; set cscalar_decls; set zscalar_decls; set mxarray_decls; void init_scalar_types() { const char* scalar_types[] = { "double", "float", "long", "int", "short", "char", "ulong", "uint", "ushort", "uchar", "int32_t", "int64_t", "uint32_t", "uint64_t", "bool", "size_t", "ptrdiff_t", NULL}; for (const char** s = scalar_types; *s; ++s) add_scalar_type(*s); } char *promote_int(char* name) { /* Detect C99 types: int32_t, int64_t, uint32_t, uint64_t */ if( strcmp(name,"int32_t") == 0 ) mw_use_int32_t = 1; if( strcmp(name,"int64_t") == 0 ) mw_use_int64_t = 1; if( strcmp(name,"uint32_t") == 0 ) mw_use_uint32_t = 1; if( strcmp(name,"uint64_t") == 0 ) mw_use_uint64_t = 1; if( strcmp(name,"ulong") == 0 ) mw_use_ulong = 1; if( strcmp(name,"uint") == 0 ) mw_use_uint = 1; if( strcmp(name,"ushort") == 0 ) mw_use_ushort = 1; if( strcmp(name,"uchar") == 0 ) mw_use_uchar = 1; /* Promote integers */ if( mw_promote_int == 1 ) { if( strcmp(name,"uint") == 0 ) mw_use_ulong = 1; if( strcmp(name,"int") == 0 ) return strdup("long"); if( strcmp(name,"uint") == 0 ) return strdup("ulong"); } if( mw_promote_int == 2 ) { if( strcmp(name,"uint") == 0 ) mw_use_ulong = 1; if( strcmp(name,"ulong") == 0 ) mw_use_ulong = 1; if( strcmp(name,"int") == 0 ) return strdup("long"); if( strcmp(name,"long") == 0 ) return strdup("long"); if( strcmp(name,"uint") == 0 ) return strdup("ulong"); if( strcmp(name,"ulong") == 0 ) return strdup("ulong"); } if( mw_promote_int == 3 ) { if( strcmp(name,"int") == 0 ) mw_use_int32_t = 1; if( strcmp(name,"long") == 0 ) mw_use_int64_t = 1; if( strcmp(name,"uint") == 0 ) mw_use_uint32_t = 1; if( strcmp(name,"ulong") == 0 ) mw_use_uint64_t = 1; if( strcmp(name,"int") == 0 ) return strdup("int32_t"); if( strcmp(name,"long") == 0 ) return strdup("int32_t"); if( strcmp(name,"uint") == 0 ) return strdup("uint64_t"); if( strcmp(name,"ulong") == 0 ) return strdup("uint64_t"); } if( mw_promote_int == 4 ) { if( strcmp(name,"int") == 0 ) mw_use_int64_t = 1; if( strcmp(name,"long") == 0 ) mw_use_int64_t = 1; if( strcmp(name,"uint") == 0 ) mw_use_uint64_t = 1; if( strcmp(name,"ulong") == 0 ) mw_use_uint64_t = 1; if( strcmp(name,"int") == 0 ) return strdup("int64_t"); if( strcmp(name,"long") == 0 ) return strdup("int64_t"); if( strcmp(name,"uint") == 0 ) return strdup("uint64_t"); if( strcmp(name,"ulong") == 0 ) return strdup("uint64_t"); } return name; } void add_scalar_type(const char* name) { scalar_decls.insert(name); } void add_cscalar_type(const char* name) { cscalar_decls.insert(name); } void add_zscalar_type(const char* name) { zscalar_decls.insert(name); } void add_mxarray_type(const char* name) { mxarray_decls.insert(name); } bool is_scalar_type(const char* name) { return (scalar_decls.find(name) != scalar_decls.end()); } bool is_cscalar_type(const char* name) { return (cscalar_decls.find(name) != cscalar_decls.end()); } bool is_zscalar_type(const char* name) { return (zscalar_decls.find(name) != zscalar_decls.end()); } bool is_mxarray_type(const char* name) { return (mxarray_decls.find(name) != mxarray_decls.end()); } /* -- Print the AST -- */ /* * Print a human-readable translation of the abstract syntax tree to * the output. This is only used for generating comprehensible comments * in the C code. */ void print(FILE* fp, Expr* e) { if (!e) return; fprintf(fp, "%s", e->value); if (e->next) { fprintf(fp, ", "); print(fp, e->next); } } void print(FILE* fp, TypeQual* q) { if (!q) return; if (q->qual == 'a') { fprintf(fp, "["); print(fp, q->args); fprintf(fp, "]"); } else fprintf(fp, "%c", q->qual); } void print_iospec(FILE* fp, Var* v) { if (v->iospec == 'o') fprintf(fp, "output "); else if (v->iospec == 'b') fprintf(fp, "inout "); } void print_var(FILE* fp, Var* v) { fprintf(fp, "%s", v->basetype); print(fp, v->qual); fprintf(fp, " %s", v->name); } void print_args(FILE* fp, Var* v) { if (!v) return; print_iospec(fp, v); print_var(fp, v); if (v->next) { fprintf(fp, ", "); print_args(fp, v->next); } } void print(FILE* fp, Func* f) { if (!f) return; if (f->ret) { print_var(fp, f->ret); fprintf(fp, " = "); } if (f->thisv) fprintf(fp, "%s->%s.", f->thisv, f->classv); fprintf(fp, "%s(", f->funcv); print_args(fp, f->args); fprintf(fp, ");\n"); } /* -- ID string -- */ /* * The ID string is a compressed text representation of the AST for * a function. We replace all the variable names by the letter 'x' * so that when we have the same function call with different arguments, * we will generate the same signature. */ string id_string(Expr* e) { if (!e) return ""; return "x" + id_string(e->next); } string id_string(TypeQual* q) { if (!q) return ""; if (q->qual == 'a') return "[" + id_string(q->args) + "]"; else return (string() + q->qual); } string id_string(Var* v) { if (!v) return ""; string name; if (v->iospec == 'i') name += "i "; else if (v->iospec == 'o') name += "o "; else name += "io "; name += promote_int(v->basetype); name += id_string(v->qual); if (v->tinfo == VT_const) { name += " "; name += v->name; } if (v->next) { name += ", "; name += id_string(v->next); } return name; } string id_string(Func* f) { if (!f) return ""; string name; if (f->ret) { name += id_string(f->ret); name += " = "; } if (f->thisv) { name += f->thisv; name += "->"; name += f->classv; name += "."; } name += f->funcv; name += "("; name += id_string(f->args); name += ")"; return name; } /* -- Destroy an AST -- */ void destroy(Expr* e) { if (!e) return; destroy(e->next); delete[] e->value; delete e; } void destroy(TypeQual* q) { if (!q) return; destroy(q->args); delete q; } void destroy(Var* v) { if (!v) return; destroy(v->next); destroy(v->qual); delete[] v->basetype; delete[] v->name; delete v; } void destroy(Func* f) { while (f) { Func* oldf = f; f = f->next; destroy(oldf->same_next); destroy(oldf->ret); if (oldf->thisv) delete[] oldf->thisv; if (oldf->classv) delete[] oldf->classv; delete[] oldf->funcv; destroy(oldf->args); delete oldf; } } void destroy(InheritsDecl* i) { if (!i) return; destroy(i->next); delete i; } void destroy_inherits() { map::iterator i = class_decls.begin(); for (; i != class_decls.end(); ++i) { destroy(i->second); i->second = NULL; } } mwrap-1.1.1/src/mwrap-ast.h000066400000000000000000000115471430266125200155240ustar00rootroot00000000000000/* * mwrap-ast.h * MWrap abstract syntax tree declarations. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #ifndef MWRAP_AST_H #define MWRAP_AST_H #include #include #include #include using std::string; using std::map; using std::set; enum { VT_unk, // Unknown VT_obj, // Object VT_array, // Numeric array (real) VT_carray, // Numeric array (single complex) VT_zarray, // Numeric array (double complex) VT_rarray, // Reference to numeric array VT_scalar, // Numeric scalar (real) VT_cscalar, // Numeric scalar (single complex) VT_zscalar, // Numeric scalar (double complex) VT_string, // Char string VT_mx, // mxArray VT_p_obj, // Pointer to object VT_p_scalar, // Pointer to scalar (real) VT_p_cscalar, // Pointer to scalar (single complex) VT_p_zscalar, // Pointer to scalar (double complex) VT_r_obj, // Reference to object VT_r_scalar, // Reference to scalar (real) VT_r_cscalar, // Reference to scalar (single complex) VT_r_zscalar, // Reference to scalar (double complex) VT_const, // Constant expression }; struct InheritsDecl { InheritsDecl(char* name, InheritsDecl* next) : name(name), next(next) {} char* name; // Name of inherited class InheritsDecl* next; }; struct Expr { Expr(char* value) : value(value), next(NULL), input_label(-1) {} int input_label; // Index of dim variable in input arg list char* value; // Expression to be evaluated to get dimension Expr* next; }; struct TypeQual { TypeQual(char qual, Expr* args) : qual(qual), args(args) {} char qual; // Pointer ('*'), ref ('&'), array ('a'), or nothing (0) Expr* args; // Array / cstring dimension list }; struct Var { Var(char iospec, char* basetype, TypeQual* qual, char* name) : iospec(iospec), basetype(basetype), qual(qual), tinfo(VT_unk), name(name), next(NULL), input_label(-1), output_label(-1) {} int input_label; // Index in input arg list int output_label; // Index in output arg list char iospec; // Indicate input ('i'), output ('o'), or both ('b') char* basetype; // Name of the base type TypeQual* qual; // Type qualifier (pointer, ref, etc) int tinfo; // General type identifier (see VT_* list above) char* name; // MATLAB text for variable name (or value) Var* next; }; struct Func { Func(char* thisv, char* classv, char* funcv, const string& fname, int line) : fname(fname), line(line), fort(false), id(-1), thisv(thisv), classv(classv), funcv(funcv), args(NULL), ret(NULL), next(NULL), same_next(NULL) {} string fname; // Name of file where this function was defined int line; // Number of the line where the function was defined bool fort; // Flag whether this is a FORTRAN function int id; // Identifier (used for numbering stub functions) char* thisv; // This var (only for methods) char* classv; // Class type (only for methods or 'new' calls) char* funcv; // Function or method name Var* args; // Arguments Var* ret; // Return variable Func* next; // Next in ordinary linked list Func* same_next; // Next in list of type-identical calls }; extern "C" char* mwrap_strdup(const char* s); extern map class_decls; void add_inherits(const char* childname, InheritsDecl* ilist); extern set scalar_decls; extern set cscalar_decls; extern set zscalar_decls; extern set mxarray_decls; void init_scalar_types(); char *promote_int(char* name); void add_scalar_type(const char* name); void add_cscalar_type(const char* name); void add_zscalar_type(const char* name); void add_mxarray_type(const char* name); bool is_scalar_type(const char* name); bool is_cscalar_type(const char* name); bool is_zscalar_type(const char* name); bool is_mxarray_type(const char* name); string id_string(Func* f); int typecheck(Func* func, int line); void print(FILE* fp, Func* func); void print_matlab_call(FILE* fp, Func* func, const char* mexfunc); void print_mex_init(FILE* fp); void print_mex_file(FILE* fp, Func* f); void mex_c99_complex(FILE* fp); void mex_cpp_complex(FILE* fp); void destroy(Func* func); void destroy(InheritsDecl* ilist); void destroy_inherits(); extern bool mw_generate_catch; extern bool mw_use_c99_complex; extern bool mw_use_cpp_complex; extern int mw_promote_int; extern int mw_use_int32_t; extern int mw_use_int64_t; extern int mw_use_uint32_t; extern int mw_use_uint64_t; extern int mw_use_longlong; extern int mw_use_ulonglong; extern int mw_use_ulong; extern int mw_use_uint; extern int mw_use_ushort; extern int mw_use_uchar; #endif /* MWRAP_AST_H */ mwrap-1.1.1/src/mwrap-cgen.cc000066400000000000000000001411671430266125200160110ustar00rootroot00000000000000/* * mwrap-cgen.cc * Generate C MEX file from MWrap AST. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include #include #include #include #include "mwrap-ast.h" #include "mwrap-support.h" /* -- General utility functions -- */ /* * Check whether a tinfo is an array type */ bool is_array(int tinfo) { return (tinfo == VT_array || tinfo == VT_carray || tinfo == VT_zarray); } /* * Check whether a tinfo is an array type */ bool is_obj(int tinfo) { return (tinfo == VT_obj || tinfo == VT_p_obj || tinfo == VT_r_obj); } /* * A function has a nullable return value if it returns a non-object * type for which a NULL pointer value makes sense. */ bool nullable_return(Func* f) { return (f->ret && (f->ret->tinfo == VT_string || is_array(f->ret->tinfo) || f->ret->tinfo == VT_p_scalar || f->ret->tinfo == VT_p_cscalar || f->ret->tinfo == VT_p_zscalar)); } /* * Get the name of a variable into the provided buffer. */ const char* vname(Var* v, char* buf) { if (v->iospec == 'o') sprintf(buf, "out%d_", v->output_label); else sprintf(buf, "in%d_", v->input_label); return buf; } /* * Check whether there are any FORTRAN routines in the list. */ bool has_fortran(Func* f) { for (; f; f=f->next) if (f->fort) return true; return false; } /* * Check whether the specified variable is complex */ bool complex_tinfo(Var* v) { return (v->tinfo == VT_carray || v->tinfo == VT_zarray || v->tinfo == VT_cscalar || v->tinfo == VT_zscalar || v->tinfo == VT_r_cscalar || v->tinfo == VT_r_zscalar || v->tinfo == VT_p_cscalar || v->tinfo == VT_p_zscalar); } /* * Count routines in the list. */ int max_routine_id(Func* f) { int maxid = 0; for (; f; f=f->next) if (f->id > maxid) maxid = f->id; return maxid; } /* -- Generate standard complex type definitions -- */ void mex_cpp_complex(FILE* fp) { fprintf(fp, "#include \n" "\n" "typedef std::complex dcomplex;\n" "#define real_dcomplex(z) std::real(z)\n" "#define imag_dcomplex(z) std::imag(z)\n" "#define setz_dcomplex(z,r,i) *z = dcomplex(r,i)\n" "\n" "typedef std::complex fcomplex;\n" "#define real_fcomplex(z) std::real(z)\n" "#define imag_fcomplex(z) std::imag(z)\n" "#define setz_fcomplex(z,r,i) *z = fcomplex(r,i)\n\n"); } void mex_c99_complex(FILE* fp) { fprintf(fp, "#include \n" "\n" "typedef _Complex double dcomplex;\n" "#define real_dcomplex(z) creal(z)\n" "#define imag_dcomplex(z) cimag(z)\n" "#define setz_dcomplex(z,r,i) *z = r + i*_Complex_I\n" "\n" "typedef _Complex float fcomplex;\n" "#define real_fcomplex(z) crealf(z)\n" "#define imag_fcomplex(z) cimagf(z)\n" "#define setz_fcomplex(z,r,i) *z = r + i*_Complex_I\n\n"); } /* -- Generate scalar conversion info -- */ /* * For each scalar type T, we define methods to convert a double array * to/from a T array, and to handle return of a pointer to a single T * (which might be NULL). */ void mex_define_copiers(FILE* fp, const char* name) { /* Skip C99 int32_t, int64_t, uint32_t, uint64_t, if not detected */ if( (strcmp(name, "int32_t") == 0 ) && ( mw_use_int32_t == 0 ) ) return; if( (strcmp(name, "int64_t") == 0 ) && ( mw_use_int64_t == 0 ) ) return; if( (strcmp(name, "uint32_t") == 0 ) && ( mw_use_uint32_t == 0 ) ) return; if( (strcmp(name, "uint64_t") == 0 ) && ( mw_use_uint64_t == 0 ) ) return; if( (strcmp(name, "ulong") == 0 ) && ( mw_use_ulong == 0 ) ) return; if( (strcmp(name, "uint") == 0 ) && ( mw_use_uint == 0 ) ) return; if( (strcmp(name, "ushort") == 0 ) && ( mw_use_ushort == 0 ) ) return; if( (strcmp(name, "uchar") == 0 ) && ( mw_use_uchar == 0 ) ) return; /* Define copiers */ fprintf(fp, "mxWrapGetArrayDef(mxWrapGetArray_%s, %s)\n", name, name); fprintf(fp, "mxWrapCopyDef (mxWrapCopy_%s, %s)\n", name, name); fprintf(fp, "mxWrapReturnDef (mxWrapReturn_%s, %s)\n", name, name); /* Single precision */ fprintf(fp, "mxWrapGetArrayDef_single(mxWrapGetArray_single_%s, %s)\n", name, name); fprintf(fp, "mxWrapCopyDef_single (mxWrapCopy_single_%s, %s)\n", name, name); fprintf(fp, "mxWrapReturnDef_single (mxWrapReturn_single_%s, %s)\n", name, name); } void mex_define_zcopiers(FILE* fp, const char* name, const char* ztype) { /* Define complex copiers */ fprintf(fp, "mxWrapGetScalarZDef(mxWrapGetScalar_%s, %s,\n" " %s, setz_%s)\n", name, name, ztype, name); fprintf(fp, "mxWrapGetArrayZDef (mxWrapGetArray_%s, %s,\n" " %s, setz_%s)\n", name, name, ztype, name); fprintf(fp, "mxWrapCopyZDef (mxWrapCopy_%s, %s,\n" " real_%s, imag_%s)\n", name, name, name, name); fprintf(fp, "mxWrapReturnZDef (mxWrapReturn_%s, %s,\n" " real_%s, imag_%s)\n", name, name, name, name); /* Single precision */ fprintf(fp, "mxWrapGetScalarZDef_single(mxWrapGetScalar_single_%s, %s,\n" " %s, setz_%s)\n", name, name, ztype, name); fprintf(fp, "mxWrapGetArrayZDef_single (mxWrapGetArray_single_%s, %s,\n" " %s, setz_%s)\n", name, name, ztype, name); fprintf(fp, "mxWrapCopyZDef_single (mxWrapCopy_single_%s, %s,\n" " real_%s, imag_%s)\n", name, name, name, name); fprintf(fp, "mxWrapReturnZDef_single (mxWrapReturn_single_%s, %s,\n" " real_%s, imag_%s)\n", name, name, name, name); } void mex_define_copiers(FILE* fp) { fprintf(fp, "\n\n\n"); fprintf(fp, "/* Array copier definitions */\n"); for( set::iterator iter = scalar_decls.begin(); iter != scalar_decls.end(); ++iter) mex_define_copiers(fp, iter->c_str()); for( set::iterator iter = cscalar_decls.begin(); iter != cscalar_decls.end(); ++iter) mex_define_zcopiers(fp, iter->c_str(), "float"); for( set::iterator iter = zscalar_decls.begin(); iter != zscalar_decls.end(); ++iter) mex_define_zcopiers(fp, iter->c_str(), "double"); fprintf(fp, "\n"); } /* -- Handle FORTRAN name mangling -- */ /* * For each FORTRAN function, we define a macro version of the name * starting with MWF77_, which will handle the various name-mangling * issues that come up. We support three name mangling conventions for * now: all upper (no underscore mangling); all lower, single underscore; * and all lower, single underscore, double underscore for names that * contain an underscore (f2c). */ void mex_define_caps_fname(FILE* fp, Func* f) { fprintf(fp, "#define MWF77_%s ", f->funcv); for (char* s = f->funcv; *s; ++s) fputc(toupper(*s), fp); fprintf(fp, "\n"); } void mex_define_caps_fnames(FILE* fp, Func* f) { set fnames; for (; f; f = f->next) { if (f->fort && fnames.find(f->funcv) == fnames.end()) { mex_define_caps_fname(fp, f); fnames.insert(f->funcv); } } } void mex_define_underscore1_fname(FILE* fp, Func* f) { fprintf(fp, "#define MWF77_%s ", f->funcv); for (char* s = f->funcv; *s; ++s) fputc(tolower(*s), fp); fprintf(fp, "_\n"); } void mex_define_underscore1_fnames(FILE* fp, Func* f) { set fnames; for (; f; f = f->next) { if (f->fort && fnames.find(f->funcv) == fnames.end()) { mex_define_underscore1_fname(fp, f); fnames.insert(f->funcv); } } } void mex_define_underscore0_fname(FILE* fp, Func* f) { fprintf(fp, "#define MWF77_%s ", f->funcv); for (char* s = f->funcv; *s; ++s) fputc(tolower(*s), fp); fprintf(fp, "\n"); } void mex_define_underscore0_fnames(FILE* fp, Func* f) { set fnames; for (; f; f = f->next) { if (f->fort && fnames.find(f->funcv) == fnames.end()) { mex_define_underscore0_fname(fp, f); fnames.insert(f->funcv); } } } void mex_define_f2c_fname(FILE* fp, Func* f) { fprintf(fp, "#define MWF77_%s ", f->funcv); bool has_underscore = false; for (char* s = f->funcv; *s; ++s) { has_underscore = (has_underscore || (*s == '_')); fputc(tolower(*s), fp); } if (has_underscore) fprintf(fp, "__\n"); else fprintf(fp, "_\n"); } void mex_define_f2c_fnames(FILE* fp, Func* f) { set fnames; for (; f; f = f->next) { if (f->fort && fnames.find(f->funcv) == fnames.end()) { mex_define_f2c_fname(fp, f); fnames.insert(f->funcv); } } } void mex_define_fnames(FILE* fp, Func* f) { fprintf(fp, "#if defined(MWF77_CAPS)\n"); mex_define_caps_fnames(fp, f); fprintf(fp, "#elif defined(MWF77_UNDERSCORE1)\n"); mex_define_underscore1_fnames(fp, f); fprintf(fp, "#elif defined(MWF77_UNDERSCORE0)\n"); mex_define_underscore0_fnames(fp, f); fprintf(fp, "#else /* f2c convention */\n"); mex_define_f2c_fnames(fp, f); fprintf(fp, "#endif\n\n"); } /* -- Handle FORTRAN declarations -- */ /* * We assume unless told otherwise that all FORTRAN functions need * prototypes, which we will generate. */ void mex_fortran_arg(FILE* fp, Var* v) { if (!v) return; if (v->tinfo == VT_mx) fprintf(fp, "const mxArray*"); else fprintf(fp, "%s*", v->basetype); if (v->next) { fprintf(fp, ", "); mex_fortran_arg(fp, v->next); } } void mex_fortran_decl(FILE* fp, Func* f) { if (f->ret) fprintf(fp, "%s ", f->ret->basetype); else fprintf(fp, "MWF77_RETURN "); fprintf(fp, "MWF77_%s(", f->funcv); mex_fortran_arg(fp, f->args); fprintf(fp, ");\n"); } void mex_fortran_decls(FILE* fp, Func* f) { fprintf(fp, "#ifdef __cplusplus\n" "extern \"C\" { /* Prevent C++ name mangling */\n" "#endif\n\n" "#ifndef MWF77_RETURN\n" "#define MWF77_RETURN int\n" "#endif\n\n"); set fnames; for (; f; f = f->next) { if (f->fort && fnames.find(f->funcv) == fnames.end()) { mex_fortran_decl(fp, f); fnames.insert(f->funcv); } } fprintf(fp, "\n#ifdef __cplusplus\n" "} /* end extern C */\n" "#endif\n\n"); } /* -- Generate class conversion info -- */ /* * For every parent class, we define a getter method that can take a * string of the form "T:value" and interpret the value as a pointer * to T for every child class T. We want to get an *exact* match with * the child pointer type and then cast that pointer to the parent type * in the C++ code, because otherwise we don't get the right behavior * with multiple inheritance (i.e. when a cast actually changes the pointer * value). */ void mex_casting_getter_type(FILE* fp, const char* name) { fprintf(fp, " %s* p_%s = NULL;\n" " sscanf(pbuf, \"%s:%%p\", &p_%s);\n" " if (p_%s)\n" " return p_%s;\n\n", name, name, name, name, name, name); } void mex_casting_getter(FILE* fp, const char* cname, InheritsDecl* inherits) { fprintf(fp, "\n%s* mxWrapGetP_%s(const mxArray* a, const char** e)\n", cname, cname); fprintf(fp, "{\n" " char pbuf[128];\n" " if (mxGetClassID(a) == mxDOUBLE_CLASS &&\n" " mxGetM(a)*mxGetN(a) == 1 &&\n" "#if MX_HAS_INTERLEAVED_COMPLEX\n" " ((mxIsComplex(a) ? *mxGetComplexDoubles(a) == 0 : *mxGetDoubles(a) == 0)\n" "#else\n" " *mxGetPr(a) == 0\n" "#endif\n" " )\n" " return NULL;\n" " if (!mxIsChar(a)) {\n" "#ifdef R2008OO\n" " mxArray* ap = mxGetProperty(a, 0, \"mwptr\");\n" " if (ap)\n" " return mxWrapGetP_%s(ap, e);\n" "#endif\n" " *e = \"Invalid pointer\";\n" " return NULL;\n" " }\n" " mxGetString(a, pbuf, sizeof(pbuf));\n\n", cname); mex_casting_getter_type(fp, cname); for (InheritsDecl* i = inherits; i; i = i->next) mex_casting_getter_type(fp, i->name); fprintf(fp, " *e = \"Invalid pointer to %s\";\n" " return NULL;\n" "}\n\n", cname); } void mex_casting_getters(FILE* fp) { map::iterator i = class_decls.begin(); for (; i != class_decls.end(); ++i) mex_casting_getter(fp, i->first.c_str(), i->second); } void mex_cast_get_p(FILE* fp, const char* basetype, int input_label) { fprintf(fp, " in%d_ = ", input_label); if (is_mxarray_type(basetype)) fprintf(fp, "mxWrapGet_%s(prhs[%d], &mw_err_txt_);\n", basetype, input_label); else if (class_decls.find(basetype) == class_decls.end()) fprintf(fp, "(%s*) mxWrapGetP(prhs[%d], \"%s:%%p\", &mw_err_txt_);\n", basetype, input_label, basetype); else fprintf(fp, "mxWrapGetP_%s(prhs[%d], &mw_err_txt_);\n", basetype, input_label); fprintf(fp, " if (mw_err_txt_)\n" " goto mw_err_label;\n"); } /* -- Mex stub variable declarations -- */ /* * In each stub function, we declare local variables corresponding to * arguments (input and output), return values, and dimension parameters. * We use the names inX_, outX_, and dimX_ to represent input/inout, output * and dimension parameters, where X is the index in the prhs array or * plhs array. */ void mex_declare_type(char* typebuf, Var* v) { if (is_obj(v->tinfo) || is_array(v->tinfo)) sprintf(typebuf, "%s*", v->basetype); else if (v->tinfo == VT_rarray) sprintf(typebuf, "const %s*", v->basetype); else if (v->tinfo == VT_scalar || v->tinfo == VT_cscalar || v->tinfo == VT_zscalar || v->tinfo == VT_r_scalar || v->tinfo == VT_r_cscalar || v->tinfo == VT_r_zscalar || v->tinfo == VT_p_scalar || v->tinfo == VT_p_cscalar || v->tinfo == VT_p_zscalar) sprintf(typebuf, "%s", v->basetype); else if (v->tinfo == VT_string) sprintf(typebuf, "char*"); else if (v->tinfo == VT_mx && v->iospec == 'i') sprintf(typebuf, "const mxArray*"); else if (v->tinfo == VT_mx && v->iospec == 'o') sprintf(typebuf, "mxArray*"); else { fprintf(stderr, "v->tinfo == %d; v->name = %s\n", v->tinfo, v->name); assert(0); } } void mex_declare_in_args(FILE* fp, Var* v) { if (!v) return; if ((v->iospec == 'i' || v->iospec == 'b') && v->tinfo != VT_const) { char typebuf[128]; mex_declare_type(typebuf, v); if (is_array(v->tinfo) || is_obj(v->tinfo) || v->tinfo == VT_string) { fprintf(fp, " %-10s in%d_ =0; /* %-10s */\n", typebuf, v->input_label, v->name); } else { fprintf(fp, " %-10s in%d_; /* %-10s */\n", typebuf, v->input_label, v->name); } } mex_declare_in_args(fp, v->next); } void mex_declare_out_args(FILE* fp, Var* v) { if (!v) return; if (v->iospec == 'o' && v->tinfo != VT_mx) { char typebuf[128]; mex_declare_type(typebuf, v); if (is_array(v->tinfo) || is_obj(v->tinfo) || v->tinfo == VT_string) { fprintf(fp, " %-10s out%d_=0; /* %-10s */\n", typebuf, v->output_label, v->name); } else { fprintf(fp, " %-10s out%d_; /* %-10s */\n", typebuf, v->output_label, v->name); } } mex_declare_out_args(fp, v->next); } void mex_declare_dim_args(FILE* fp, Expr* e) { if (!e) return; fprintf(fp, " %-10s dim%d_; /* %-10s */\n", "mwSize", e->input_label, e->value); mex_declare_dim_args(fp, e->next); } void mex_declare_dim_args(FILE* fp, Var* v) { if (!v) return; if (v->qual) mex_declare_dim_args(fp, v->qual->args); mex_declare_dim_args(fp, v->next); } void mex_declare_return(FILE* fp, Var* v) { mex_declare_out_args(fp, v); } void mex_declare_args(FILE* fp, Func* f) { if (f->thisv) { char typebuf[128]; strcpy(typebuf, f->classv); strcat(typebuf, "*"); fprintf(fp, " %-10s in%d_ =0; /* %-10s */\n", typebuf, 0, f->thisv); } mex_declare_in_args(fp, f->args); if (!nullable_return(f)) mex_declare_return(fp, f->ret); mex_declare_out_args(fp, f->args); mex_declare_dim_args(fp, f->ret); mex_declare_dim_args(fp, f->args); if (f->ret || f->args || f->thisv) fprintf(fp, "\n"); } /* -- Mex stub dimension retrieval -- */ /* * After declaring local variables, we copy in the dimension arguments. */ int mex_unpack_dims(FILE* fp, Expr* e) { if (!e) return 0; fprintf(fp, " dim%d_ = (mwSize) mxWrapGetScalar(prhs[%d], &mw_err_txt_);\n", e->input_label, e->input_label); return mex_unpack_dims(fp, e->next)+1; } int mex_unpack_dims(FILE* fp, Var* v) { if (!v) return 0; if (v->qual) return mex_unpack_dims(fp, v->qual->args) + mex_unpack_dims(fp, v->next); return mex_unpack_dims(fp, v->next); } void mex_unpack_dims(FILE* fp, Func* f) { if (mex_unpack_dims(fp, f->ret) || mex_unpack_dims(fp, f->args)) fprintf(fp, "\n"); } /* -- Mex stub dimension checks -- */ /* * For input and inout arrays where the dimensions are given explicitly * in the call, we check that the dimensions of the MATLAB array passed * in agree with the dimensions in the dimension arguments. */ void mex_check_dims(FILE* fp, Var* v) { if (!v) return; if (v->iospec != 'o' && is_array(v->tinfo) && v->qual && v->qual->args) { Expr* a = v->qual->args; if (a->next) { fprintf(fp, " if (mxGetM(prhs[%d]) != dim%d_ ||\n" " mxGetN(prhs[%d]) != dim%d_) {\n" " mw_err_txt_ = \"Bad argument size: %s\";\n" " goto mw_err_label;\n" " }\n\n", v->input_label, a->input_label, v->input_label, a->next->input_label, v->name); } else { fprintf(fp, " if (mxGetM(prhs[%d])*mxGetN(prhs[%d]) != dim%d_) {\n" " mw_err_txt_ = \"Bad argument size: %s\";" " goto mw_err_label;\n" " }\n\n", v->input_label, v->input_label, a->input_label, v->name); } } mex_check_dims(fp, v->next); } void mex_check_dims(FILE* fp, Func* f) { if (!fp) return; mex_check_dims(fp, f->args); } /* -- Output size data -- */ /* * Generate code to compute the size of an array from dim arguments. */ void mex_alloc_size1(FILE* fp, Expr* e) { if (!e) return; fprintf(fp, "dim%d_", e->input_label); if (e->next) { fprintf(fp, "*"); mex_alloc_size1(fp, e->next); } } void mex_alloc_size(FILE* fp, Expr* e) { if (!e) fprintf(fp, "1"); else mex_alloc_size1(fp, e); } /* -- Unpack input data -- */ /* * Generate code to copy data from the prhs array into the inX_ * local variables in a stub function. Note that for input strings, * we take any explicit dimension information as what the user wants -- * if the string is too long to fit in that explicit dimension, our * generated code will return with an error message. */ void mex_unpack_input_array(FILE* fp, Var* v) { fprintf(fp, " if (mxGetM(prhs[%d])*mxGetN(prhs[%d]) != 0) {\n", v->input_label, v->input_label); if (strcmp(v->basetype, "fcomplex") == 0) fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxSINGLE_CLASS )\n" " mw_err_txt_ = \"Invalid array argument, mxSINGLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n" " in%d_ = mxWrapGetArray_single_%s(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->input_label, v->basetype, v->input_label); else if (strcmp(v->basetype, "dcomplex") == 0) fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxDOUBLE_CLASS )\n" " mw_err_txt_ = \"Invalid array argument, mxDOUBLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n" " in%d_ = mxWrapGetArray_%s(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->input_label, v->basetype, v->input_label); else if (strcmp(v->basetype, "float") == 0) if (v->iospec == 'i') fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxSINGLE_CLASS )\n" " mw_err_txt_ = \"Invalid array argument, mxSINGLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n" "#if MX_HAS_INTERLEAVED_COMPLEX\n" " in%d_ = mxGetSingles(prhs[%d]);\n" "#else\n" " in%d_ = (float*) mxGetData(prhs[%d]);\n" "#endif\n", v->input_label, v->input_label, v->input_label, v->input_label, v->input_label); else fprintf(fp, " in%d_ = mxWrapGetArray_single_%s(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->basetype, v->input_label); else if (strcmp(v->basetype, "double") == 0) if (v->iospec == 'i') fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxDOUBLE_CLASS )\n" " mw_err_txt_ = \"Invalid array argument, mxDOUBLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n" "#if MX_HAS_INTERLEAVED_COMPLEX\n" " in%d_ = mxGetDoubles(prhs[%d]);\n" "#else\n" " in%d_ = mxGetPr(prhs[%d]);\n" "#endif\n", v->input_label, v->input_label, v->input_label, v->input_label, v->input_label); else fprintf(fp, " in%d_ = mxWrapGetArray_%s(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->basetype, v->input_label); else fprintf(fp, " in%d_ = mxWrapGetArray_%s(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->basetype, v->input_label); fprintf(fp, " } else\n" " in%d_ = NULL;\n", v->input_label); } void mex_unpack_input_string(FILE* fp, Var* v) { if (!(v->qual && v->qual->args)) fprintf(fp, " in%d_ = mxWrapGetString(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->input_label); else { fprintf(fp, " in%d_ = (char*) mxMalloc(", v->input_label); mex_alloc_size(fp, v->qual->args); fprintf(fp, "*sizeof(char));\n"); fprintf(fp, " if (mxGetString(prhs[%d], in%d_, ", v->input_label, v->input_label); mex_alloc_size(fp, v->qual->args); fprintf(fp, ") != 0) {\n" " mw_err_txt_ = \"Invalid string argument\";\n" " goto mw_err_label;\n" " }\n"); } } void mex_unpack_inputs(FILE* fp, Var* v) { if (!v) return; if (v->iospec == 'o') { mex_unpack_inputs(fp, v->next); return; } if (is_obj(v->tinfo)) mex_cast_get_p(fp, v->basetype, v->input_label); else if (is_array(v->tinfo)) mex_unpack_input_array(fp, v); else if (v->tinfo == VT_scalar || v->tinfo == VT_r_scalar || v->tinfo == VT_p_scalar) { if ( strcmp(v->basetype,"float") == 0 ) fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxSINGLE_CLASS )\n" " mw_err_txt_ = \"Invalid scalar argument, mxSINGLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n" " in%d_ = (%s) mxWrapGetScalar_single(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->input_label, v->basetype, v->input_label); else fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxDOUBLE_CLASS )\n" " mw_err_txt_ = \"Invalid scalar argument, mxDOUBLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n" " in%d_ = (%s) mxWrapGetScalar(prhs[%d], &mw_err_txt_);\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", v->input_label, v->input_label, v->basetype, v->input_label); } else if (v->tinfo == VT_cscalar || v->tinfo == VT_zscalar || v->tinfo == VT_r_cscalar || v->tinfo == VT_r_zscalar || v->tinfo == VT_p_cscalar || v->tinfo == VT_p_zscalar) { if ( strcmp(v->basetype,"fcomplex") == 0 ) { fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxSINGLE_CLASS )\n" " mw_err_txt_ = \"Invalid scalar argument, mxSINGLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n", v->input_label); fprintf(fp, " mxWrapGetScalar_single_%s(&in%d_, prhs[%d]);\n", v->basetype, v->input_label, v->input_label); } else { fprintf(fp, " if( mxGetClassID(prhs[%d]) != mxDOUBLE_CLASS )\n" " mw_err_txt_ = \"Invalid scalar argument, mxDOUBLE_CLASS expected\";\n" " if (mw_err_txt_) goto mw_err_label;\n", v->input_label); fprintf(fp, " mxWrapGetScalar_%s(&in%d_, prhs[%d]);\n", v->basetype, v->input_label, v->input_label); } } else if (v->tinfo == VT_string) mex_unpack_input_string(fp, v); else if (v->tinfo == VT_mx) fprintf(fp, " in%d_ = prhs[%d];\n", v->input_label, v->input_label); mex_unpack_inputs(fp, v->next); } void mex_unpack_inputs(FILE* fp, Func* f) { if (f->thisv) mex_cast_get_p(fp, f->classv, 0); mex_unpack_inputs(fp, f->args); } /* -- Check input data -- */ /* * If an input variable is declared to be an object or a reference to * an object, we check to make sure the pointer passed in is not NULL. */ void mex_check_inputs(FILE* fp, Var* v) { if (!v) return; if (v->iospec != 'o' && (v->tinfo == VT_obj || v->tinfo == VT_r_obj)) fprintf(fp, " if (!in%d_) {\n" " mw_err_txt_ = \"Argument %s cannot be null\";\n" " goto mw_err_label;\n" " }\n", v->input_label, v->name); mex_check_inputs(fp, v->next); } void mex_check_inputs(FILE* fp, Func* f) { mex_check_inputs(fp, f->args); } /* -- Allocate output data -- */ /* * When we allocate data for output variables, we only allocate data * for *pure* output variables. For input/output variables, we'll use * the scratch copy of the input as the scratch copy of the output, too. */ void mex_alloc_output(FILE* fp, Var* v, bool return_flag) { if (!v) return; if (v->iospec == 'o') { if (!return_flag && is_obj(v->tinfo) && is_mxarray_type(v->basetype)) { fprintf(fp, " out%d_ = mxWrapAlloc_%s();\n", v->output_label, v->basetype); } else if (is_array(v->tinfo)) { fprintf(fp, " out%d_ = (%s*) mxMalloc(", v->output_label, v->basetype); mex_alloc_size(fp, v->qual->args); fprintf(fp, "*sizeof(%s));\n", v->basetype); } else if (v->tinfo == VT_rarray) { fprintf(fp, " out%d_ = (%s*) NULL;\n", v->output_label, v->basetype); } else if (v->tinfo == VT_string) { fprintf(fp, " out%d_ = (char*) mxMalloc(", v->output_label); mex_alloc_size(fp, v->qual->args); fprintf(fp, "*sizeof(char));\n"); } } mex_alloc_output(fp, v->next, return_flag); } void mex_alloc_output(FILE* fp, Func* f) { if (!nullable_return(f)) mex_alloc_output(fp, f->ret, true); mex_alloc_output(fp, f->args, false); } /* -- Record that this routine was called -- */ /* * For coverage testing, we keep a counter of the number of times each * stub is called. */ void mex_record_call(FILE* fp, Func* f) { fprintf(fp, " if (mexprofrecord_)\n" " mexprofrecord_[%d]++;\n", f->id); } /* -- Make the call -- */ /* * The only non-obvious aspect of the call line is the way that return * values are treated. The biggest issue is that functions can return * NULL, and we need to present that to the user in some reasonable * way that won't be confused with an ordinary return -- this is why * we use 0 to represent a null return for a string or an object, but * we use an empty array to represent a null return for a numeric * object. A secondary issue has to do with strings -- we won't know the * size of a return string until after we have it in hand. Both because * of the possibility of NULL returns and because of the indeterminate size * of strings, we allocate space to hold return values *with* the call, * rather than setting up space before the call. */ void mex_make_call(FILE* fp, Var* v, int first) { if (!v) return; if (!first) fprintf(fp, ", "); char namebuf[128]; if (v->tinfo == VT_obj || v->tinfo == VT_r_obj) fprintf(fp, "*%s", vname(v, namebuf)); else if (v->tinfo == VT_mx && v->iospec == 'o') fprintf(fp, "plhs+%d", v->output_label); else if (v->tinfo == VT_p_scalar || v->tinfo == VT_p_cscalar || v->tinfo == VT_p_zscalar) fprintf(fp, "&%s", vname(v, namebuf)); else if (v->tinfo == VT_const) fprintf(fp, "%s", v->name); else fprintf(fp, "%s", vname(v, namebuf)); mex_make_call(fp, v->next, 0); } void mex_make_call(FILE* fp, Func* f) { if (f->thisv) fprintf(fp, "in0_->"); if (strcmp(f->funcv, "new") == 0) fprintf(fp, "new %s(", f->classv); else { if (f->fort) fprintf(fp, "MWF77_"); fprintf(fp, "%s(", f->funcv); } mex_make_call(fp, f->args, 1); fprintf(fp, ")"); } void mex_make_stmt(FILE* fp, Func* f) { if (!f) return; if (f->thisv) fprintf(fp, " if (!in0_) {\n" " mw_err_txt_ = \"Cannot dispatch to NULL\";\n" " goto mw_err_label;\n" " }\n"); if (mw_generate_catch) fprintf(fp, " try {\n "); if (f->ret) { Var* v = f->ret; if (v->tinfo == VT_obj) { if (is_mxarray_type(v->basetype)) { fprintf(fp, " plhs[0] = mxWrapSet_%s(&(", v->basetype); mex_make_call(fp, f); fprintf(fp ,"));\n"); } else { fprintf(fp, " out0_ = new %s(", v->basetype); mex_make_call(fp, f); fprintf(fp ,");\n"); } } else if (is_array(v->tinfo)) { fprintf(fp, " plhs[0] = mxWrapReturn_%s(", v->basetype); mex_make_call(fp, f); fprintf(fp, ", "); Expr* e = v->qual->args; if (e && e->next && !e->next->next) { fprintf(fp, " dim%d_, dim%d_);\n", e->input_label, e->next->input_label); } else { mex_alloc_size(fp, v->qual->args); fprintf(fp, ", 1);\n"); } } else if (v->tinfo == VT_scalar || v->tinfo == VT_r_scalar || v->tinfo == VT_cscalar || v->tinfo == VT_r_cscalar || v->tinfo == VT_zscalar || v->tinfo == VT_r_zscalar) { fprintf(fp, " out0_ = "); mex_make_call(fp, f); fprintf(fp, ";\n"); } else if (v->tinfo == VT_string) { fprintf(fp, " plhs[0] = mxWrapStrncpy("); mex_make_call(fp, f); fprintf(fp, ");\n"); } else if (v->tinfo == VT_mx) { fprintf(fp, " plhs[0] = "); mex_make_call(fp, f); fprintf(fp, ";\n"); } else if (v->tinfo == VT_p_obj) { if (is_mxarray_type(v->basetype)) { fprintf(fp, " plhs[0] = mxWrapSet_%s(", v->basetype); mex_make_call(fp, f); fprintf(fp, ");\n"); } else { fprintf(fp, " out0_ = "); mex_make_call(fp, f); fprintf(fp, ";\n"); } } else if (v->tinfo == VT_p_scalar || v->tinfo == VT_p_cscalar || v->tinfo == VT_p_zscalar) { fprintf(fp, " plhs[0] = mxWrapReturn_%s(", v->basetype); mex_make_call(fp, f); fprintf(fp, ", 1, 1);\n"); } else if (v->tinfo == VT_r_obj) { if (is_mxarray_type(v->basetype)) { fprintf(fp, " plhs[0] = mxWrapSet_%s(&(", v->basetype); mex_make_call(fp, f); fprintf(fp, "));\n"); } else { fprintf(fp, " out0_ = &("); mex_make_call(fp, f); fprintf(fp, ");\n"); } } } else { fprintf(fp, " "); mex_make_call(fp, f); fprintf(fp, ";\n"); } if (mw_generate_catch) fprintf(fp, " } catch(...) {\n" " mw_err_txt_ = \"Caught C++ exception from %s\";\n" " }\n" " if (mw_err_txt_)\n" " goto mw_err_label;\n", f->funcv); } /* -- Marshal the results -- */ /* * Copy inout arguments, output arguments, and any simple return * arguments into the plhs array. */ void mex_marshal_array(FILE* fp, Var* v) { Expr* e = v->qual->args; char namebuf[128]; const char* mtype = complex_tinfo(v) ? "mxCOMPLEX" : "mxREAL"; const char* ws = " "; if (v->tinfo == VT_rarray) { ws = " "; fprintf(fp, " if (out%d_ == NULL) {\n", v->output_label); fprintf(fp, " plhs[%d] = mxCreateDoubleMatrix(0,0, mxREAL);\n", v->output_label); fprintf(fp, " } else {\n"); } if (!e) { // No dimension info -- must be an inout array if (strcmp(v->basetype, "float") == 0 || strcmp(v->basetype, "fcomplex") == 0) { fprintf(fp, "%splhs[%d] = mxCreateNumericMatrix(" "mxGetM(prhs[%d]), mxGetN(prhs[%d]), mxSINGLE_CLASS, %s);\n", ws, v->output_label, v->input_label, v->input_label, mtype); fprintf(fp, "%smxWrapCopy_single_%s(plhs[%d], in%d_, ", ws, v->basetype, v->output_label, v->input_label); } else { fprintf(fp, "%splhs[%d] = mxCreateDoubleMatrix(" "mxGetM(prhs[%d]), mxGetN(prhs[%d]), %s);\n", ws, v->output_label, v->input_label, v->input_label, mtype); fprintf(fp, "%smxWrapCopy_%s(plhs[%d], in%d_, ", ws, v->basetype, v->output_label, v->input_label); } fprintf(fp, "mxGetM(prhs[%d])*mxGetN(prhs[%d])", v->input_label, v->input_label); fprintf(fp, ");\n"); } else if (!(e->next)) { // Only size given if (strcmp(v->basetype, "float") == 0 || strcmp(v->basetype, "fcomplex") == 0) { fprintf(fp, "%splhs[%d] = mxCreateNumericMatrix(dim%d_, 1, mxSINGLE_CLASS, %s);\n", ws, v->output_label, e->input_label, mtype); fprintf(fp, "%smxWrapCopy_single_%s(plhs[%d], %s, ", ws, v->basetype, v->output_label, vname(v, namebuf)); } else { fprintf(fp, "%splhs[%d] = mxCreateDoubleMatrix(dim%d_, 1, %s);\n", ws, v->output_label, e->input_label, mtype); fprintf(fp, "%smxWrapCopy_%s(plhs[%d], %s, ", ws, v->basetype, v->output_label, vname(v, namebuf)); } fprintf(fp, "dim%d_", e->input_label); fprintf(fp, ");\n"); } else if (!(e->next->next)) { // Two dimensions given if (strcmp(v->basetype, "float") == 0 || strcmp(v->basetype, "fcomplex") == 0) { fprintf(fp, "%splhs[%d] = mxCreateNumericMatrix(" "dim%d_, dim%d_, mxSINGLE_CLASS, %s);\n", ws, v->output_label, e->input_label, e->next->input_label, mtype); fprintf(fp, "%smxWrapCopy_single_%s(plhs[%d], %s, ", ws, v->basetype, v->output_label, vname(v, namebuf)); } else { fprintf(fp, "%splhs[%d] = mxCreateDoubleMatrix(" "dim%d_, dim%d_, %s);\n", ws, v->output_label, e->input_label, e->next->input_label, mtype); fprintf(fp, "%smxWrapCopy_%s(plhs[%d], %s, ", ws, v->basetype, v->output_label, vname(v, namebuf)); } fprintf(fp, "dim%d_*dim%d_", e->input_label, e->next->input_label); fprintf(fp, ");\n"); } else { // Three or more dimensions given -- punt and make it 1D if (strcmp(v->basetype, "float") == 0 || strcmp(v->basetype, "fcomplex") == 0) { fprintf(fp, "%splhs[%d] = mxCreateNumericMatrix(", ws, v->output_label); mex_alloc_size(fp, e); fprintf(fp, ", 1, mxSINGLE_CLASS, %s);\n", mtype); fprintf(fp, "%smxWrapCopy_single_%s(plhs[%d], %s, ", ws, v->basetype, v->output_label, vname(v, namebuf)); } else { fprintf(fp, "%splhs[%d] = mxCreateDoubleMatrix(", ws, v->output_label); mex_alloc_size(fp, e); fprintf(fp, ", 1, %s);\n", mtype); fprintf(fp, "%smxWrapCopy_%s(plhs[%d], %s, ", ws, v->basetype, v->output_label, vname(v, namebuf)); } mex_alloc_size(fp, e); fprintf(fp, ");\n"); } if (v->tinfo == VT_rarray) { fprintf(fp, " }\n"); } } void mex_marshal_result(FILE* fp, Var* v, bool return_flag) { char namebuf[1280]; if (is_obj(v->tinfo) && is_mxarray_type(v->basetype)) { if (!return_flag) fprintf(fp, " plhs[%d] = mxWrapSet_%s(%s);\n", v->output_label, v->basetype, vname(v,namebuf)); } else if (is_obj(v->tinfo)) fprintf(fp, " plhs[%d] = mxWrapCreateP(out%d_, \"%s:%%p\");\n", v->output_label, v->output_label, v->basetype); else if (is_array(v->tinfo) || v->tinfo == VT_rarray) mex_marshal_array(fp, v); else if (v->tinfo == VT_scalar || v->tinfo == VT_r_scalar || v->tinfo == VT_p_scalar) fprintf(fp, "#if MX_HAS_INTERLEAVED_COMPLEX\n" " plhs[%d] = mxCreateDoubleMatrix(1, 1, mxREAL);\n" " *mxGetDoubles(plhs[%d]) = %s;\n" "#else\n" " plhs[%d] = mxCreateDoubleMatrix(1, 1, mxREAL);\n" " *mxGetPr(plhs[%d]) = %s;\n" "#endif\n", v->output_label, v->output_label, vname(v, namebuf), v->output_label, v->output_label, vname(v, namebuf)); else if (v->tinfo == VT_cscalar || v->tinfo == VT_zscalar || v->tinfo == VT_r_cscalar || v->tinfo == VT_r_zscalar || v->tinfo == VT_p_cscalar || v->tinfo == VT_p_zscalar) fprintf(fp, "#if MX_HAS_INTERLEAVED_COMPLEX\n" " plhs[%d] = mxCreateDoubleMatrix(1, 1, mxCOMPLEX);\n" " *mxGetComplexDoubles(plhs[%d]) = %s;\n" "#else\n" " plhs[%d] = mxCreateDoubleMatrix(1, 1, mxCOMPLEX);\n" " *mxGetPr(plhs[%d]) = real_%s(%s);\n" " *mxGetPi(plhs[%d]) = imag_%s(%s);\n" "#endif\n", v->output_label, v->output_label, vname(v, namebuf), v->output_label, v->output_label, v->basetype, vname(v, namebuf), v->output_label, v->basetype, vname(v, namebuf)); else if (v->tinfo == VT_string) fprintf(fp, " plhs[%d] = mxCreateString(%s);\n", v->output_label, vname(v, namebuf)); } void mex_marshal_results(FILE* fp, Var* v, bool return_flag) { if (!v) return; if (v->iospec != 'i') mex_marshal_result(fp, v, return_flag); mex_marshal_results(fp, v->next, return_flag); } void mex_marshal_results(FILE* fp, Func* f) { if (!nullable_return(f)) mex_marshal_results(fp, f->ret, true); mex_marshal_results(fp, f->args, false); } /* -- Deallocate temporary data -- */ /* * Free scratch arrays allocated to hold input copies and output * storage. */ void mex_dealloc(FILE* fp, Var* v, bool return_flag) { if (!v) return; if (is_array(v->tinfo) || v->tinfo == VT_string) { if (v->iospec == 'o') fprintf(fp, " if (out%d_) mxFree(out%d_);\n", v->output_label, v->output_label); else if (v->iospec == 'b' || !(strcmp(v->basetype, "double") == 0 || strcmp(v->basetype, "float") == 0) ) fprintf(fp, " if (in%d_) mxFree(in%d_);\n", v->input_label, v->input_label); } else if (is_obj(v->tinfo) && is_mxarray_type(v->basetype)) { if (v->iospec == 'i' || v->iospec == 'b') fprintf(fp, " if (in%d_) mxWrapFree_%s(in%d_);\n", v->input_label, v->basetype, v->input_label); else if (v->iospec == 'o' && !return_flag) fprintf(fp, " if (out%d_) mxWrapFree_%s(out%d_);\n", v->output_label, v->basetype, v->output_label); } mex_dealloc(fp, v->next, return_flag); } void mex_dealloc(FILE* fp, Func* f) { if (!nullable_return(f)) mex_dealloc(fp, f->ret, true); mex_dealloc(fp, f->args, false); } /* -- Generate mex stub -- */ /* * Print a MEX stub function. We generate one of these for each * distinct call line in the input files. */ void print_c_comment(FILE* fp, Func* f) { fprintf(fp, "/* ---- %s: %d ----\n * ", f->fname.c_str(), f->line); print(fp, f); for (Func* fsame = f->same_next; fsame; fsame = fsame->next) fprintf(fp, " * Also at %s: %d\n", fsame->fname.c_str(), fsame->line); fprintf(fp, " */\n"); } void print_mex_stub(FILE* fp, Func* f) { print_c_comment(fp, f); fprintf(fp, "static const char* stubids%d_ = \"%s\";\n\n" "void mexStub%d(int nlhs, mxArray* plhs[],\n" " int nrhs, const mxArray* prhs[])\n" "{\n" " const char* mw_err_txt_ = 0;\n", f->id, id_string(f).c_str(), f->id); mex_declare_args(fp, f); mex_unpack_dims(fp, f); mex_check_dims(fp, f); mex_unpack_inputs(fp, f); mex_check_inputs(fp, f); mex_alloc_output(fp, f); mex_record_call(fp, f); mex_make_stmt(fp, f); mex_marshal_results(fp, f); fprintf(fp, "\nmw_err_label:\n"); mex_dealloc(fp, f); fprintf(fp, " if (mw_err_txt_)\n" " mexErrMsgTxt(mw_err_txt_);\n" "}\n\n"); } /* -- Generate profiler output routine -- */ /* * The profiler / coverage testing routines include starting, * ending, and reporting. Starting the profiler locks the MEX file * in memory. */ void make_profile_output(FILE* fp, Func* f, const char* printfunc) { fprintf(fp, " if (!mexprofrecord_)\n" " %s\"Profiler inactive\\n\");\n", printfunc); for (; f; f = f->next) { fprintf(fp, " %s\"%%d calls to %s:%d", printfunc, f->fname.c_str(), f->line); for (Func* fsame = f->same_next; fsame; fsame = fsame->next) fprintf(fp, " (%s:%d)", fsame->fname.c_str(), fsame->line); fprintf(fp, "\\n\", mexprofrecord_[%d]);\n", f->id); } } /* -- Generate MEX file -- */ /* * Generate the overall C file to be fed into MEX. This consists of * basic support code (from mwrap-support.c), type conversion * routines, all the call stubs, and a main dispatcher that decides * which stub to call. */ void print_mex_stubs(FILE* fp, Func* f) { for (; f; f = f->next) print_mex_stub(fp, f); } void print_mex_else_cases(FILE* fp, Func* f) { for (Func* fcall = f; fcall; fcall = fcall->next) fprintf(fp, " else if (strcmp(id, stubids%d_) == 0)\n" " mexStub%d(nlhs,plhs, nrhs-1,prhs+1);\n", fcall->id, fcall->id); int maxid = max_routine_id(f); fprintf(fp, " else if (strcmp(id, \"*profile on*\") == 0) {\n" " if (!mexprofrecord_) {\n" " mexprofrecord_ = (int*) malloc(%d * sizeof(int));\n" " mexLock();\n" " }\n" " memset(mexprofrecord_, 0, %d * sizeof(int));\n" " } else if (strcmp(id, \"*profile off*\") == 0) {\n" " if (mexprofrecord_) {\n" " free(mexprofrecord_);\n" " mexUnlock();\n" " }\n" " mexprofrecord_ = NULL;\n" " } else if (strcmp(id, \"*profile report*\") == 0) {\n", maxid+1, maxid+1); make_profile_output(fp, f, "mexPrintf("); fprintf(fp, " } else if (strcmp(id, \"*profile log*\") == 0) {\n" " FILE* logfp;\n" " if (nrhs != 2 || mxGetString(prhs[1], id, sizeof(id)) != 0)\n" " mexErrMsgTxt(\"Must have two string arguments\");\n" " logfp = fopen(id, \"w+\");\n" " if (!logfp)\n" " mexErrMsgTxt(\"Cannot open log for output\");\n"); make_profile_output(fp, f, "fprintf(logfp, "); fprintf(fp, " fclose(logfp);\n"); fprintf(fp, " } else\n" " mexErrMsgTxt(\"Unknown identifier\");\n"); } const char* mwrap_banner = "/* --------------------------------------------------- */\n" "/* Automatically generated by mwrap */\n" "/* --------------------------------------------------- */\n\n"; const char* mexBase = "/* ----\n" " */\n" "void mexFunction(int nlhs, mxArray* plhs[],\n" " int nrhs, const mxArray* prhs[])\n" "{\n" " char id[512];\n" " if (nrhs == 0) {\n" " mexPrintf(\"Mex function installed\\n\");\n" " return;\n" " }\n\n" " if (mxGetString(prhs[0], id, sizeof(id)) != 0)\n" " mexErrMsgTxt(\"Identifier should be a string\");\n"; const char* mwrap_compat_type_support = "/*\n" " * Compiler compatibility extensions\n" " */\n" "\n" "typedef unsigned long ulong;\n" "typedef unsigned int uint;\n" "typedef unsigned short ushort;\n" "typedef unsigned char uchar;\n" "typedef long long longlong;\n" "typedef unsigned long long ulonglong;\n"; // "#ifndef ulong\n" // "# define ulong unsigned long\n" // "#endif\n" // "#ifndef uint\n" // "# define uint unsigned int\n" // "#endif\n" // "#ifndef ushort\n" // "# define ushort unsigned short\n" // "#endif\n" // "#ifndef uchar\n" // "# define uchar unsigned char\n" // "#endif\n" // "\n" // "#ifndef longlong\n" // "# define longlong long long\n" // "#endif\n" // "#ifndef ulonglong\n" // "# define ulonglong unsigned long long\n" // "#endif\n"; void print_mex_init(FILE* fp) { fprintf(fp, "%s", mwrap_banner); fprintf(fp, "%s", mex_header); fprintf(fp, "\n"); if (mw_use_c99_complex) mex_c99_complex(fp); else if (mw_use_cpp_complex) mex_cpp_complex(fp); // fprintf(fp, "\n"); // fprintf(fp, "%s", mwrap_compat_type_support); // fprintf(fp, "\n"); } void print_mex_file(FILE* fp, Func* f) { mex_define_copiers(fp); mex_casting_getters(fp); if (has_fortran(f)) { mex_define_fnames(fp, f); mex_fortran_decls(fp, f); } print_mex_stubs(fp, f); fprintf(fp, "%s", mexBase); print_mex_else_cases(fp, f); fprintf(fp, "}\n\n"); } mwrap-1.1.1/src/mwrap-mgen.cc000066400000000000000000000042311430266125200160110ustar00rootroot00000000000000/* * mwrap-mgen.cc * Generate MATLAB scripts from MWrap AST. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include #include #include #include #include "mwrap-ast.h" /* -- Output MATLAB call code -- */ /* * Each call is translated to MATLAB code of the form * * mex_id_ = 'identifier from id_string'; * [result1, result2, ...] = mexfunc(mex_id_, in1, ..., dim1, dim2, ...); * * where dim1, dim2, ... are any explicitly provided array dimensions. */ int has_output_args(Var* v) { if (!v) return 0; if (v->iospec == 'o' || v->iospec == 'b') return 1; else return has_output_args(v->next); } void print_output_args(FILE* fp, Var* v, int& first) { if (!v) return; if (v->iospec == 'o' || v->iospec == 'b') { if (!first) fprintf(fp, ", "); fprintf(fp, "%s", v->name); first = 0; } print_output_args(fp, v->next, first); } void print_input_args(FILE* fp, Var* v) { if (!v) return; if (v->tinfo == VT_const) fprintf(fp, ", 0"); else if (v->iospec == 'i' || v->iospec == 'b') fprintf(fp, ", %s", v->name); print_input_args(fp, v->next); } void print_dimension_args(FILE* fp, Expr* e) { if (!e) return; fprintf(fp, ", %s", e->value); print_dimension_args(fp, e->next); } void print_dimension_args(FILE* fp, Var* v) { if (!v) return; if (v->qual) print_dimension_args(fp, v->qual->args); print_dimension_args(fp, v->next); } void print_matlab_call(FILE* fp, Func* f, const char* mexfunc) { fprintf(fp, "mex_id_ = '%s';\n", id_string(f).c_str()); if (f->ret || has_output_args(f->args)) { int first = 1; fprintf(fp, "["); print_output_args(fp, f->ret, first); print_output_args(fp, f->args, first); fprintf(fp, "] = "); } fprintf(fp, "%s(mex_id_", mexfunc); if (f->thisv) fprintf(fp, ", %s", f->thisv); print_input_args(fp, f->args); print_dimension_args(fp, f->ret); print_dimension_args(fp, f->args); fprintf(fp, ");\n"); } mwrap-1.1.1/src/mwrap-support.c000066400000000000000000000544761430266125200164540ustar00rootroot00000000000000/* Code generated by mwrap 1.1 */ /* Copyright statement for mwrap: mwrap -- MEX file generation for MATLAB and Octave Copyright (c) 2007-2008 David Bindel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. You may distribute a work that contains part or all of the source code generated by mwrap under the terms of your choice. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #if MX_HAS_INTERLEAVED_COMPLEX #include #endif /* * Records for call profile. */ int* mexprofrecord_= NULL; /* * Support routines for copying data into and out of the MEX stubs, R2018a */ #if MX_HAS_INTERLEAVED_COMPLEX void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e) { void* p = NULL; #ifdef R2008OO mxArray* ap; #endif if (mxGetClassID(a) == mxDOUBLE_CLASS && mxIsComplex(a) ) { if( mxGetM(a)*mxGetN(a) == 1 && (*mxGetComplexDoubles(a)).real == 0 ) return NULL; } if (mxGetClassID(a) == mxDOUBLE_CLASS && !mxIsComplex(a) ) { if( mxGetM(a)*mxGetN(a) == 1 && *mxGetDoubles(a) == 0) return NULL; } if (mxIsChar(a)) { char pbuf[128]; mxGetString(a, pbuf, sizeof(pbuf)); sscanf(pbuf, fmt, &p); } #ifdef R2008OO else if (ap = mxGetProperty(a, 0, "mwptr")) { return mxWrapGetP(ap, fmt, e); } #endif if (p == 0) *e = "Invalid pointer"; return p; } mxArray* mxWrapCreateP(void* p, const char* fmt) { if (p == 0) { mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); *mxGetDoubles(z) = 0; return z; } else { char pbuf[128]; sprintf(pbuf, fmt, p); return mxCreateString(pbuf); } } mxArray* mxWrapStrncpy(const char* s) { if (s) { return mxCreateString(s); } else { mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); *mxGetDoubles(z) = 0; return z; } } char* mxWrapGetString(const mxArray* a, const char** e) { char* s; mwSize slen; if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { *e = "Invalid string argument"; return NULL; } slen = mxGetM(a)*mxGetN(a) + 1; s = (char*) mxMalloc(slen); if (mxGetM(a)*mxGetN(a) == 0) *s = 0; else mxGetString(a, s, slen); return s; } double mxWrapGetScalar(const mxArray* a, const char** e) { if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { *e = "Invalid scalar argument"; return 0; } if( mxIsComplex(a) ) return (double) (*mxGetComplexDoubles(a)).real; else return (double) (*mxGetDoubles(a)); } #define mxWrapGetArrayDef(func, T) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ double* q; \ mxComplexDouble* z; \ if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexDoubles(a); \ for (i = 0; i < arraylen; ++i) \ *p++ = (T) (*z++).real; \ } \ else \ { \ q = mxGetDoubles(a); \ for (i = 0; i < arraylen; ++i) \ *p++ = (T) (*q++); \ } \ return array; \ } #define mxWrapCopyDef(func, T) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ double* p; \ mxComplexDouble* z; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexDoubles(a); \ for (i = 0; i < n; ++i) \ (*z++).real = (double) *q++; \ (*z++).imag = 0; \ } \ else \ { \ p = mxGetDoubles(a); \ for (i = 0; i < n; ++i) \ *p++ = (double) *q++; \ } \ } #define mxWrapReturnDef(func, T) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ double* p; \ if (!q) { \ return mxCreateDoubleMatrix(0,0, mxREAL); \ } else { \ mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ p = mxGetDoubles(a); \ for (i = 0; i < m*n; ++i) \ *p++ = (double) *q++; \ return a; \ } \ } #define mxWrapGetScalarZDef(func, T, ZT, setz) \ void func(T* z, const mxArray* a) \ { \ if( mxIsComplex(a) ) \ { \ setz(z, (ZT) (*mxGetComplexDoubles(a)).real, (ZT) (*mxGetComplexDoubles(a)).imag); \ } \ else \ { \ setz(z, (ZT) (*mxGetComplexDoubles(a)).real, (ZT) 0); \ } \ } #define mxWrapGetArrayZDef(func, T, ZT, setz) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ double* q; \ mxComplexDouble* z; \ if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexDoubles(a); \ for (i = 0; i < arraylen; ++i) { \ setz(p, (ZT) (*z).real, (ZT) (*z).imag); \ ++p; ++z; } \ } \ else \ { \ q = mxGetDoubles(a); \ for (i = 0; i < arraylen; ++i) { \ setz(p, (ZT) (*q), (ZT) 0 ); \ ++p; ++q; } \ } \ return array; \ } #define mxWrapCopyZDef(func, T, freal, fimag) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ double* p; \ mxComplexDouble* z; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexDoubles(a); \ for (i = 0; i < n; ++i) { \ (*z).real = freal(*q); \ (*z).imag = fimag(*q); \ ++z; ++q; } \ } \ else \ { \ p = mxGetDoubles(a); \ for (i = 0; i < n; ++i) \ *p++ = freal(*q++); \ } \ } #define mxWrapReturnZDef(func, T, freal, fimag) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ mxComplexDouble* p; \ if (!q) { \ return mxCreateDoubleMatrix(0,0, mxCOMPLEX); \ } else { \ mxArray* a = mxCreateDoubleMatrix(m,n, mxCOMPLEX); \ p = mxGetComplexDoubles(a); \ for (i = 0; i < m*n; ++i) { \ (*p).real = freal(*q); \ (*p).imag = fimag(*q); \ ++p; ++q; } \ return a; \ } \ } void* mxWrapGetP_single(const mxArray* a, const char* fmt, const char** e) { void* p = NULL; #ifdef R2008OO mxArray* ap; #endif if (mxGetClassID(a) == mxSINGLE_CLASS && mxIsComplex(a) ) { if( mxGetM(a)*mxGetN(a) == 1 && (*mxGetComplexSingles(a)).real == 0 ) return NULL; } if (mxGetClassID(a) == mxSINGLE_CLASS && !mxIsComplex(a) ) { if( mxGetM(a)*mxGetN(a) == 1 && *mxGetSingles(a) == 0) return NULL; } if (mxIsChar(a)) { char pbuf[128]; mxGetString(a, pbuf, sizeof(pbuf)); sscanf(pbuf, fmt, &p); } #ifdef R2008OO else if (ap = mxGetProperty(a, 0, "mwptr")) { return mxWrapGetP(ap, fmt, e); } #endif if (p == 0) *e = "Invalid pointer"; return p; } mxArray* mxWrapCreateP_single(void* p, const char* fmt) { if (p == 0) { mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); *mxGetSingles(z) = 0; return z; } else { char pbuf[128]; sprintf(pbuf, fmt, p); return mxCreateString(pbuf); } } mxArray* mxWrapStrncpy_single(const char* s) { if (s) { return mxCreateString(s); } else { mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); *mxGetSingles(z) = 0; return z; } } char* mxWrapGetString_single(const mxArray* a, const char** e) { char* s; mwSize slen; if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { *e = "Invalid string argument"; return NULL; } slen = mxGetM(a)*mxGetN(a) + 1; s = (char*) mxMalloc(slen); if (mxGetM(a)*mxGetN(a) == 0) *s = 0; else mxGetString(a, s, slen); return s; } float mxWrapGetScalar_single(const mxArray* a, const char** e) { if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { *e = "Invalid scalar argument"; return 0; } if( mxIsComplex(a) ) return (float) (*mxGetComplexSingles(a)).real; else return (float) (*mxGetSingles(a)); } #define mxWrapGetArrayDef_single(func, T) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ float* q; \ mxComplexSingle* z; \ if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexSingles(a); \ for (i = 0; i < arraylen; ++i) \ *p++ = (T) (*z++).real; \ } \ else \ { \ q = mxGetSingles(a); \ for (i = 0; i < arraylen; ++i) \ *p++ = (T) (*q++); \ } \ return array; \ } #define mxWrapCopyDef_single(func, T) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ float* p; \ mxComplexSingle* z; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexSingles(a); \ for (i = 0; i < n; ++i) \ (*z++).real = (float) *q++; \ (*z++).imag = 0; \ } \ else \ { \ p = mxGetSingles(a); \ for (i = 0; i < n; ++i) \ *p++ = (float) *q++; \ } \ } #define mxWrapReturnDef_single(func, T) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ float* p; \ if (!q) { \ return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxREAL); \ } else { \ mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxREAL); \ p = mxGetSingles(a); \ for (i = 0; i < m*n; ++i) \ *p++ = (float) *q++; \ return a; \ } \ } #define mxWrapGetScalarZDef_single(func, T, ZT, setz) \ void func(T* z, const mxArray* a) \ { \ if( mxIsComplex(a) ) \ { \ setz(z, (ZT) (*mxGetComplexSingles(a)).real, (ZT) (*mxGetComplexSingles(a)).imag); \ } \ else \ { \ setz(z, (ZT) (*mxGetComplexSingles(a)).real, (ZT) 0); \ } \ } #define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ float* q; \ mxComplexSingle* z; \ if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexSingles(a); \ for (i = 0; i < arraylen; ++i) { \ setz(p, (ZT) (*z).real, (ZT) (*z).imag); \ ++p; ++z; } \ } \ else \ { \ q = mxGetSingles(a); \ for (i = 0; i < arraylen; ++i) { \ setz(p, (ZT) (*q), (ZT) 0 ); \ ++p; ++q; } \ } \ return array; \ } #define mxWrapCopyZDef_single(func, T, freal, fimag) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ float* p; \ mxComplexSingle* z; \ if( mxIsComplex(a) ) \ { \ z = mxGetComplexSingles(a); \ for (i = 0; i < n; ++i) { \ (*z).real = freal(*q); \ (*z).imag = fimag(*q); \ ++z; ++q; } \ } \ else \ { \ p = mxGetSingles(a); \ for (i = 0; i < n; ++i) \ *p++ = freal(*q++); \ } \ } #define mxWrapReturnZDef_single(func, T, freal, fimag) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ mxComplexSingle* p; \ if (!q) { \ return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxCOMPLEX); \ } else { \ mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxCOMPLEX); \ p = mxGetComplexSingles(a); \ for (i = 0; i < m*n; ++i) { \ (*p).real = freal(*q); \ (*p).imag = fimag(*q); \ ++p; ++q; } \ return a; \ } \ } #else /* * Support routines for copying data into and out of the MEX stubs, -R2017b */ void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e) { void* p = 0; #ifdef R2008OO mxArray* ap; #endif if (mxGetClassID(a) == mxDOUBLE_CLASS && mxGetM(a)*mxGetN(a) == 1 && *mxGetPr(a) == 0) return p; if (mxIsChar(a)) { char pbuf[128]; mxGetString(a, pbuf, sizeof(pbuf)); sscanf(pbuf, fmt, &p); } #ifdef R2008OO else if (ap = mxGetProperty(a, 0, "mwptr")) { return mxWrapGetP(ap, fmt, e); } #endif if (p == 0) *e = "Invalid pointer"; return p; } mxArray* mxWrapCreateP(void* p, const char* fmt) { if (p == 0) { mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); *mxGetPr(z) = 0; return z; } else { char pbuf[128]; sprintf(pbuf, fmt, p); return mxCreateString(pbuf); } } mxArray* mxWrapStrncpy(const char* s) { if (s) { return mxCreateString(s); } else { mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL); *mxGetPr(z) = 0; return z; } } double mxWrapGetScalar(const mxArray* a, const char** e) { if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { *e = "Invalid scalar argument"; return 0; } return *mxGetPr(a); } char* mxWrapGetString(const mxArray* a, const char** e) { char* s; mwSize slen; if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { *e = "Invalid string argument"; return NULL; } slen = mxGetM(a)*mxGetN(a) + 1; s = (char*) mxMalloc(slen); if (mxGetM(a)*mxGetN(a) == 0) *s = 0; else mxGetString(a, s, slen); return s; } #define mxWrapGetArrayDef(func, T) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ double* q; \ if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ q = mxGetPr(a); \ for (i = 0; i < arraylen; ++i) \ *p++ = (T) (*q++); \ return array; \ } #define mxWrapCopyDef(func, T) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ double* p = mxGetPr(a); \ for (i = 0; i < n; ++i) \ *p++ = *q++; \ } #define mxWrapReturnDef(func, T) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ double* p; \ if (!q) { \ return mxCreateDoubleMatrix(0,0, mxREAL); \ } else { \ mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \ p = mxGetPr(a); \ for (i = 0; i < m*n; ++i) \ *p++ = *q++; \ return a; \ } \ } #define mxWrapGetScalarZDef(func, T, ZT, setz) \ void func(T* z, const mxArray* a) \ { \ double* pr = mxGetPr(a); \ double* pi = mxGetPi(a); \ setz(z, (ZT) *pr, (pi ? (ZT) *pi : (ZT) 0)); \ } #define mxWrapGetArrayZDef(func, T, ZT, setz) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ double* qr; \ double* qi; \ if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ *e = "Invalid array argument, mxDOUBLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ qr = mxGetPr(a); \ qi = mxGetPi(a); \ for (i = 0; i < arraylen; ++i) { \ ZT val_qr = *qr++; \ ZT val_qi = (qi ? (ZT) *qi++ : (ZT) 0); \ setz(p, val_qr, val_qi); \ ++p; \ } \ return array; \ } #define mxWrapCopyZDef(func, T, real, imag) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ double* pr = mxGetPr(a); \ double* pi = mxGetPi(a); \ for (i = 0; i < n; ++i) { \ *pr++ = real(*q); \ *pi++ = imag(*q); \ ++q; \ } \ } #define mxWrapReturnZDef(func, T, real, imag) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ double* pr; \ double* pi; \ if (!q) { \ return mxCreateDoubleMatrix(0,0, mxCOMPLEX); \ } else { \ mxArray* a = mxCreateDoubleMatrix(m,n, mxCOMPLEX); \ pr = mxGetPr(a); \ pi = mxGetPi(a); \ for (i = 0; i < m*n; ++i) { \ *pr++ = real(*q); \ *pi++ = imag(*q); \ ++q; \ } \ return a; \ } \ } void* mxWrapGetP_single(const mxArray* a, const char* fmt, const char** e) { void* p = 0; #ifdef R2008OO mxArray* ap; #endif if (mxGetClassID(a) == mxSINGLE_CLASS && mxGetM(a)*mxGetN(a) == 1 && *((float*)mxGetData(a)) == 0) return p; if (mxIsChar(a)) { char pbuf[128]; mxGetString(a, pbuf, sizeof(pbuf)); sscanf(pbuf, fmt, &p); } #ifdef R2008OO else if (ap = mxGetProperty(a, 0, "mwptr")) { return mxWrapGetP(ap, fmt, e); } #endif if (p == 0) *e = "Invalid pointer"; return p; } mxArray* mxWrapCreateP_single(void* p, const char* fmt) { if (p == 0) { mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); *((float*)mxGetData(z)) = 0; return z; } else { char pbuf[128]; sprintf(pbuf, fmt, p); return mxCreateString(pbuf); } } mxArray* mxWrapStrncpy_single(const char* s) { if (s) { return mxCreateString(s); } else { mxArray* z = mxCreateNumericMatrix(1,1, mxSINGLE_CLASS, mxREAL); *((float*)mxGetData(z)) = 0; return z; } } float mxWrapGetScalar_single(const mxArray* a, const char** e) { if (!a || mxGetClassID(a) != mxSINGLE_CLASS || mxGetM(a)*mxGetN(a) != 1) { *e = "Invalid scalar argument"; return 0; } return *((float*)mxGetData(a)); } char* mxWrapGetString_single(const mxArray* a, const char** e) { char* s; mwSize slen; if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) { *e = "Invalid string argument, mxSINGLE_CLASS expected"; return NULL; } slen = mxGetM(a)*mxGetN(a) + 1; s = (char*) mxMalloc(slen); if (mxGetM(a)*mxGetN(a) == 0) *s = 0; else mxGetString(a, s, slen); return s; } #define mxWrapGetArrayDef_single(func, T) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ float* q; \ if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ q = (float*) mxGetData(a); \ for (i = 0; i < arraylen; ++i) \ *p++ = (T) (*q++); \ return array; \ } #define mxWrapCopyDef_single(func, T) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ float* p = (float*) mxGetData(a); \ for (i = 0; i < n; ++i) \ *p++ = *q++; \ } #define mxWrapReturnDef_single(func, T) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ float* p; \ if (!q) { \ return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxREAL); \ } else { \ mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxREAL);\ p = (float*) mxGetData(a); \ for (i = 0; i < m*n; ++i) \ *p++ = *q++; \ return a; \ } \ } #define mxWrapGetScalarZDef_single(func, T, ZT, setz) \ void func(T* z, const mxArray* a) \ { \ float* pr = (float*) mxGetData(a); \ float* pi = (float*) mxGetImagData(a); \ setz(z, (ZT) *pr, (pi ? (ZT) *pi : (ZT) 0)); \ } #define mxWrapGetArrayZDef_single(func, T, ZT, setz) \ T* func(const mxArray* a, const char** e) \ { \ T* array; \ mwSize arraylen; \ mwIndex i; \ T* p; \ float* qr; \ float* qi; \ if (!a || mxGetClassID(a) != mxSINGLE_CLASS) { \ *e = "Invalid array argument, mxSINGLE_CLASS expected"; \ return 0; \ } \ arraylen = mxGetM(a)*mxGetN(a); \ array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \ p = array; \ qr = (float*) mxGetData(a); \ qi = (float*) mxGetImagData(a); \ for (i = 0; i < arraylen; ++i) { \ ZT val_qr = *qr++; \ ZT val_qi = (qi ? (ZT) *qi++ : (ZT) 0); \ setz(p, val_qr, val_qi); \ ++p; \ } \ return array; \ } #define mxWrapCopyZDef_single(func, T, real, imag) \ void func(mxArray* a, const T* q, mwSize n) \ { \ mwIndex i; \ float* pr = (float*) mxGetData(a); \ float* pi = (float*) mxGetImagData(a); \ for (i = 0; i < n; ++i) { \ *pr++ = real(*q); \ *pi++ = imag(*q); \ ++q; \ } \ } #define mxWrapReturnZDef_single(func, T, real, imag) \ mxArray* func(const T* q, mwSize m, mwSize n) \ { \ mwIndex i; \ float* pr; \ float* pi; \ if (!q) { \ return mxCreateNumericMatrix(0,0, mxSINGLE_CLASS, mxCOMPLEX); \ } else { \ mxArray* a = mxCreateNumericMatrix(m,n, mxSINGLE_CLASS, mxCOMPLEX);\ pr = (float*) mxGetData(a); \ pi = (float*) mxGetImagData(a); \ for (i = 0; i < m*n; ++i) { \ *pr++ = real(*q); \ *pi++ = imag(*q); \ ++q; \ } \ return a; \ } \ } #endif mwrap-1.1.1/src/mwrap-typecheck.cc000066400000000000000000000246511430266125200170520ustar00rootroot00000000000000/* * mwrap-typecheck.cc * Typecheck MWrap AST. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include #include #include #include #include #include "mwrap-ast.h" /* -- Label input / output indices -- */ /* * To each argument, we assign an input label (index of the argument * in the prhs array) and an output label (the index in the plhs * array). The protocol is that we pass input and inout arguments in * first, and then tack on all the dimensioning arguments at the end. */ void label_dim_args(Expr* e, int& icount) { if (!e) return; e->input_label = icount++; label_dim_args(e->next, icount); } void label_dim_args(Var* v, int& icount) { if (!v) return; if (v->qual) label_dim_args(v->qual->args, icount); label_dim_args(v->next, icount); } void label_args(Var* v, int& icount, int& ocount) { if (!v) return; if (v->iospec == 'i' || v->iospec == 'b') v->input_label = icount++; if (v->iospec == 'o' || v->iospec == 'b') v->output_label = ocount++; label_args(v->next, icount, ocount); } void label_args(Func* f) { int icount = 0; int ocount = 0; if (f->thisv) icount = 1; label_args(f->ret, icount, ocount); label_args(f->args, icount, ocount); label_dim_args(f->ret, icount); label_dim_args(f->args, icount); } /* -- Fortran-ize arguments -- */ /* * For FORTRAN calls, we make the following type conversions and * checks on arguments: * * - All types of scalar arguments are converted to pointer-to-scalar. * - Object arguments are forbidden * - C string arguments generate a warning * * Only scalar return values are allowed from wrapped FORTRAN functions. */ int fortranize_args(Var* v, int line) { if (!v) return 0; int errcount = 0; if (v->tinfo == VT_obj || v->tinfo == VT_p_obj || v->tinfo == VT_r_obj) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Cannot pass object %s to FORTRAN\n", v->name); ++errcount; } else if (v->tinfo == VT_rarray) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Cannot pass pointer ref %s to FORTRAN\n", v->name); ++errcount; } else if (v->tinfo == VT_string) { fprintf(stderr, "Warning (%d): ", line); fprintf(stderr, "Danger passing C string %s to FORTRAN\n", v->name); } else if (v->tinfo == VT_scalar || v->tinfo == VT_r_scalar) { v->tinfo = VT_p_scalar; } else if (v->tinfo == VT_cscalar || v->tinfo == VT_r_cscalar) { v->tinfo = VT_p_cscalar; } else if (v->tinfo == VT_zscalar || v->tinfo == VT_r_zscalar) { v->tinfo = VT_p_zscalar; } return errcount + fortranize_args(v->next, line); } int fortranize_ret(Var* v, int line) { if (!v) return 0; if (v->tinfo == VT_cscalar || v->tinfo == VT_zscalar) { fprintf(stderr, "Warning (%d): ", line); fprintf(stderr, "Danger returning complex from FORTRAN\n"); } else if (v->tinfo != VT_scalar) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Can only return scalars from FORTRAN\n"); return 1; } return 0; } int fortranize_args(Func* f, int line) { if (!f->fort) return 0; return (fortranize_args(f->args, line) + fortranize_ret(f->ret, line)); } /* -- Type info assignment and checking -- */ /* * Strictly speaking, we're doing semantic checking here -- there are a * few things we check for that don't qualify as type errors. The * assumption is that any input to the C code generator has passed the * type checker. */ int assign_scalar_tinfo(Var* v, int line, int tags, int tagp, int tagr, int taga, int tagar) { // Numeric types if (!v->qual) { v->tinfo = tags; } else if (v->qual->qual == '*') { v->tinfo = tagp; } else if (v->qual->qual == '&') { v->tinfo = tagr; } else if (v->qual->qual == 'a') { v->tinfo = taga; if (v->qual->args && v->qual->args->next && v->qual->args->next->next) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Array %s should be 1D or 2D\n", v->name); return 1; } } else if (v->qual->qual == 'r') { v->tinfo = tagar; if (tagar == VT_unk) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Array ref %s must be to a real array\n", v->name); return 1; } if (v->qual->args && v->qual->args->next && v->qual->args->next->next) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Array %s should be 1D or 2D\n", v->name); return 1; } } else { assert(0); } return 0; } int assign_tinfo(Var* v, int line) { if (is_scalar_type(v->basetype)) { return assign_scalar_tinfo(v, line, VT_scalar, VT_p_scalar, VT_r_scalar, VT_array, VT_rarray); } else if (is_cscalar_type(v->basetype)) { return assign_scalar_tinfo(v, line, VT_cscalar, VT_p_cscalar, VT_r_cscalar, VT_carray, VT_unk); } else if (is_zscalar_type(v->basetype)) { return assign_scalar_tinfo(v, line, VT_zscalar, VT_p_zscalar, VT_r_zscalar, VT_zarray, VT_unk); } else if (strcmp(v->basetype, "const") == 0) { if (v->qual) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Constant %s cannot have modifiers\n", v->name); return 1; } v->tinfo = VT_const; if (v->name[0] == '\'') { char* p_out = v->name; char* p_in = v->name; for (; *p_in; ++p_in) { if (*p_in != '\'') *p_out++ = *p_in; } *p_out++ = 0; } } else if (strcmp(v->basetype, "cstring") == 0) { // String type if (v->qual && v->qual->qual != 'a') { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "String type %s cannot have modifiers\n", v->name); return 1; } if (v->qual && v->qual->args && v->qual->args->next) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Strings are one dimensional\n"); return 1; } v->tinfo = VT_string; } else if (strcmp(v->basetype, "mxArray") == 0) { // MATLAB intrinsic type if (v->qual) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "mxArray %s cannot have modifiers\n", v->name); return 1; } v->tinfo = VT_mx; } else { // Object type if (!v->qual) v->tinfo = VT_obj; else if (v->qual->qual == '*') v->tinfo = VT_p_obj; else if (v->qual->qual == '&') v->tinfo = VT_r_obj; else if (v->qual->qual == 'a' || v->qual->qual == 'r') { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "%s cannot be an array of object %s\n", v->name, v->basetype); return 1; } else assert(0); } return 0; } int typecheck_return(Var* v, int line) { if (!v) return 0; int err = assign_tinfo(v, line); if ((v->tinfo == VT_array || v->tinfo == VT_carray || v->tinfo == VT_zarray) && !(v->qual && v->qual->args)) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Return array %s must have dims\n", v->name); ++err; } else if (v->tinfo == VT_const) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Cannot return constant\n"); ++err; } else if (v->tinfo == VT_rarray) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Ref to array %s looks just like array on return\n", v->name); ++err; } else if (v->tinfo == VT_string && v->qual) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Return string %s cannot have dims\n", v->name); ++err; } return err; } int typecheck_args(Var* v, int line) { if (!v) return 0; int err = assign_tinfo(v, line); if (v->iospec == 'i') return err + typecheck_args(v->next, line); if (isdigit(v->name[0])) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Number %s cannot be output\n", v->name); ++err; } if ((v->tinfo == VT_obj || v->tinfo == VT_p_obj || v->tinfo == VT_r_obj) && !is_mxarray_type(v->basetype)) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Object %s cannot be output\n", v->name); ++err; } else if ((v->tinfo == VT_array || v->tinfo == VT_carray || v->tinfo == VT_zarray || v->tinfo == VT_rarray) && v->iospec == 'o' && !(v->qual && v->qual->args)) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Output array %s must have dims\n", v->name); ++err; } else if (v->tinfo == VT_rarray && v->iospec != 'o') { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Array ref %s *must* be output\n", v->name); ++err; } else if (v->tinfo == VT_scalar) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Scalar %s cannot be output\n", v->name); ++err; } else if (v->tinfo == VT_const) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "Constant %s cannot be output\n", v->name); ++err; } else if (v->tinfo == VT_string && !(v->qual && v->qual->args)) { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "String %s cannot be output without size\n", v->name); ++err; } else if (v->tinfo == VT_mx && v->iospec == 'b') { fprintf(stderr, "Error (%d): ", line); fprintf(stderr, "mxArray %s cannot be used for inout\n", v->name); ++err; } return err + typecheck_args(v->next, line); } int typecheck(Func* f, int line) { label_args(f); return (typecheck_return(f->ret, line) + typecheck_args(f->args, line) + fortranize_args(f, line)); } mwrap-1.1.1/src/mwrap.l000066400000000000000000000145071430266125200147420ustar00rootroot00000000000000%{ /* * mwrap.l * Lexer for MWrap. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include "mwrap.hh" #include #include extern int listing_flag; // Output filenames from @ commands? extern int mbatching_flag; // Do we want to output on @ commands? extern int linenum; // Lexer line number extern FILE* outfp; // MATLAB output file extern FILE* outcfp; // C output file static int done_at_switch; // Set when @ redirection is done extern char* mwrap_strdup(char* s); static int is_name_char(char c) { return (isalnum(c) || c == '_'); } static char* fname_scan_line(char* s) { static char namebuf[256]; /* FIXME */ int name_start, name_end, i, j; /* Name ends at last alphanum before args */ name_end = 0; while (s[name_end] && s[name_end] != '(') ++name_end; while (name_end > 0 && !is_name_char(s[name_end])) --name_end; /* Back up to the start of the name */ name_start = name_end; while (s[name_start] > 0 && is_name_char(s[name_start])) --name_start; /* Copy the name into the buf and add .m */ for (i = name_start+1, j = 0; i <= name_end; ++i, ++j) namebuf[j] = s[i]; strcpy(namebuf+j, ".m"); return namebuf; } #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_line[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; extern void set_include_name(const char* s); extern void get_include_name(); /* The lexer switches states when it sees a specially formatted comment * as the first non-blank mode in a line. In total, there are six states: * * INITIAL - start of line * TS - ordinary text line * AS - at line (redirection) * FS - @function line (function declaration + redirection) * SS - embedded C line * BS - block of embedded C * CS - C call line * COMMS - Comment line * * Transitions are as follows. * * "$[" : INITIAL -> BS * "$]" : BS -> INITIAL * "@" : INITIAL -> AS (batching mode only) * "@function" : INITIAL -> FS * "$" : INITIAL -> SS * "#" : INITIAL -> CS * non-blank : INITIAL -> TS * newline: (AS, SS, CS, TS) -> INITIAL */ %} %s CSTATE %s SSTATE %s BSTATE %s ASTATE %s FSTATE %s TSTATE %s COMMSTATE %x INCLSTATE %% "@function" { if (mbatching_flag && outfp) fclose(outfp); BEGIN FSTATE; return NON_C_LINE; } "@include" { BEGIN INCLSTATE; return NON_C_LINE; } "@" { if (mbatching_flag && outfp) fclose(outfp); done_at_switch = 0; BEGIN ASTATE; return NON_C_LINE; } "#" { BEGIN CSTATE; } \$\[[ \t\r]*\n { BEGIN BSTATE; ++linenum; return NON_C_LINE; } "$" { BEGIN SSTATE; return NON_C_LINE; } "//" { BEGIN COMMSTATE; return NON_C_LINE; } \n { if (outfp) fprintf(outfp, "%s", yytext); ++linenum; BEGIN 0; return NON_C_LINE; } [ \t] { if (outfp) fprintf(outfp, "%s", yytext); } . { if (outfp) fprintf(outfp, "%s", yytext); BEGIN TSTATE; return NON_C_LINE; } \n { ++linenum; BEGIN 0; } . ; <> { if (--include_stack_ptr < 0) { yyterminate(); } else { yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(include_stack[include_stack_ptr]); linenum = include_stack_line[include_stack_ptr]; get_include_name(); BEGIN INCLSTATE; } } [ \t\r]* ; [^ \t\r\n]+ { if (include_stack_ptr >= MAX_INCLUDE_DEPTH) { fprintf(stderr, "Error: Includes nested too deeply"); exit(-1); } set_include_name(yytext); include_stack_line[include_stack_ptr] = linenum; include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; yyin = fopen(yytext, "r"); if (!yyin) { fprintf(stderr, "Error: Could not read '%s'\n", yytext); exit(-1); } linenum = 1; yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); BEGIN 0; } \n { ++linenum; BEGIN 0; } [^\n]+ { char* fname = fname_scan_line(yytext); if (mbatching_flag) { outfp = fopen(fname, "w+"); if (!outfp) { fprintf(stderr, "Error: Could not write %s\n", yytext); exit(-1); } } if (listing_flag) fprintf(stdout, "%s\n", fname); if (outfp) fprintf(outfp, "function%s\n", yytext); } \n { ++linenum; BEGIN 0; } [ \t\r]+ ; [^ \t\r\n]+ { if (mbatching_flag && !done_at_switch) { outfp = fopen(yytext, "w+"); if (!outfp) { fprintf(stderr, "Error: Could not write %s\n", yytext); exit(-1); } } if (listing_flag && !done_at_switch) fprintf(stdout, "%s\n", yytext); done_at_switch = 1; } \n { ++linenum; BEGIN 0; } \n { if (outfp) fprintf(outfp, "%s", yytext); ++ linenum; BEGIN 0; } . { if (outfp) fprintf(outfp, "%s", yytext); } \n { if (outcfp) fprintf(outcfp, "%s", yytext); ++linenum; BEGIN 0; } . { if (outcfp) fprintf(outcfp, "%s", yytext); } \$\][ \t\r]*\n { ++linenum; BEGIN 0; } \n { if (outcfp) fprintf(outcfp, "%s", yytext); ++linenum; } . { if (outcfp) fprintf(outcfp, "%s", yytext); } "new" { return NEW; } "FORTRAN" { return FORTRAN; } "input" { return INPUT; } "output" { return OUTPUT; } "inout" { return INOUT; } "class" { return CLASS; } "typedef" { return TYPEDEF; } ((::)?[_a-zA-Z][_a-zA-Z0-9]*)* { yylval.string = mwrap_strdup(yytext); return ID; } [0-9]+ { yylval.string = mwrap_strdup(yytext); return NUMBER; } \'[^'\n]*['\n] { yylval.string = mwrap_strdup(yytext); return STRING; } \/\/[^\n]* ; [ \t\r]+ ; \n { ++linenum; BEGIN 0; } . return yytext[0]; %% mwrap-1.1.1/src/mwrap.y000066400000000000000000000236141430266125200147560ustar00rootroot00000000000000%{ /* * mwrap.y * Parser for mwrap. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include #include #include #include "mwrap-ast.h" extern "C" { int yylex(); int yywrap(); int yyerror(const char* s); } using std::string; bool mw_generate_catch = false; // Catch C++ exceptions? bool mw_use_cpp_complex = false; // Use C++ complex types? bool mw_use_c99_complex = false; // Use C99 complex types? int mw_promote_int = 0; // Convert integer types to mwSize? int mw_use_int32_t = 0; // Use C99 int32_t? int mw_use_int64_t = 0; // Use C99 int64_t? int mw_use_uint32_t = 0; // Use C99 uint32_t? int mw_use_uint64_t = 0; // Use C99 uint64_t? int mw_use_ulong = 0; // Use unsigned long? int mw_use_uint = 0; // Use unsigned int? int mw_use_ushort = 0; // Use unsigned short? int mw_use_uchar = 0; // Use unsigned char? int listing_flag = 0; // Output filenames from @ commands? int mbatching_flag = 0; // Output on @ commands? int linenum = 0; // Lexer line number FILE* outfp = 0; // MATLAB output file FILE* outcfp = 0; // C output file static int type_errs = 0; // Number of typecheck errors static int func_id = 0; // Assign stub numbers static Func* funcs = 0; // AST - linked list of functions static Func* lastfunc = 0; // Last link in funcs list static const char* mexfunc = "mexfunction"; // Name of mex function static string current_ifname; // Current input file name #define MAX_INCLUDE_DEPTH 10 static string include_stack_names[MAX_INCLUDE_DEPTH]; extern int include_stack_ptr; extern "C" void set_include_name(const char* s) { include_stack_names[include_stack_ptr] = current_ifname; current_ifname = s; } extern "C" void get_include_name() { current_ifname = include_stack_names[include_stack_ptr].c_str(); } inline void add_func(Func* func) { static std::map func_lookup; if (!funcs) { funcs = func; lastfunc = func; return; } Func*& func_ptr = func_lookup[id_string(func)]; if (func_ptr) { func_ptr->same_next = func; } else { lastfunc->next = func; lastfunc = func; } func_ptr = func; } %} %union { char* string; struct Func* func; struct Var* var; struct TypeQual* qual; struct Expr* expr; struct InheritsDecl* inherits; char c; } %token NON_C_LINE %token NEW TYPEDEF CLASS FORTRAN %token ID %token NUMBER STRING %token INPUT OUTPUT INOUT %type func funcall %type var basevar args argsrest %type iospec %type quals aqual %type arrayspec exprs exprrest expr %type inheritslist inheritsrest %error-verbose %% statements: statement statements | ; statement: basevar '=' funcall { $3->ret = $1; $3->id = ++func_id; type_errs += typecheck($3, linenum); if (outfp) print_matlab_call(outfp, $3, mexfunc); add_func($3); } | funcall { $1->id = ++func_id; type_errs += typecheck($1, linenum); if (outfp) print_matlab_call(outfp, $1, mexfunc); add_func($1); } | tdef | classdef | NON_C_LINE | error ';' { yyerrok; } ; tdef: TYPEDEF ID ID ';' { if (strcmp($2, "numeric") == 0) { add_scalar_type($3); } else if (strcmp($2, "dcomplex") == 0) { add_zscalar_type($3); } else if (strcmp($2, "fcomplex") == 0) { add_cscalar_type($3); } else if (strcmp($2, "mxArray") == 0) { add_mxarray_type($3); } else { fprintf(stderr, "Unrecognized typespace: %s\n", $2); ++type_errs; } delete[] $2; delete[] $3; } ; classdef: CLASS ID ':' inheritslist ';' { add_inherits($2, $4); delete[] $2; destroy($4); } inheritslist: ID inheritsrest { $$ = new InheritsDecl($1, $2); } ; inheritsrest: ',' ID inheritsrest { $$ = new InheritsDecl($2, $3); } | { $$ = NULL; } ; funcall: func '(' args ')' ';' { $$ = $1; $$->args = $3; } ; args: var argsrest { $$ = $1; $$->next = $2; } | { $$ = NULL; } ; argsrest: ',' var argsrest {$$ = $2; $$->next = $3; } | { $$ = NULL; } ; basevar: ID ID { $$ = new Var('o', promote_int($1), NULL, $2); } basevar: ID quals ID { $$ = new Var('o', promote_int($1), $2, $3); } basevar: ID ID aqual { $$ = new Var('o', promote_int($1), $3, $2); } var: iospec ID ID { $$ = new Var($1, promote_int($2), NULL, $3); } var: iospec ID quals ID { $$ = new Var($1, promote_int($2), $3, $4); } var: iospec ID ID aqual { $$ = new Var($1, promote_int($2), $4, $3); } var: iospec ID NUMBER { $$ = new Var($1, promote_int($2), NULL, $3); } var: iospec ID quals NUMBER { $$ = new Var($1, promote_int($2), $3, $4); } var: iospec ID STRING { $$ = new Var($1, promote_int($2), NULL, $3); } var: iospec ID quals STRING { $$ = new Var($1, promote_int($2), $3, $4); } iospec: INPUT { $$ = 'i'; } | OUTPUT { $$ = 'o'; } | INOUT { $$ = 'b'; } | { $$ = 'i'; } ; quals: '*' { $$ = new TypeQual('*', NULL); } | '&' { $$ = new TypeQual('&', NULL); } | aqual { $$ = $1; } ; aqual: arrayspec { $$ = new TypeQual('a', $1); } | arrayspec '&' { $$ = new TypeQual('r', $1); } ; arrayspec: '[' exprs ']' { $$ = $2; } ; exprs: expr exprrest { $$ = $1; $$->next = $2; } | { $$ = NULL; } exprrest: ',' expr exprrest { $$ = $2; $$->next = $3; } | { $$ = NULL; } expr: ID { $$ = new Expr($1); } | NUMBER { $$ = new Expr($1); } func: ID '-' '>' ID '.' ID { $$ = new Func($1, $4, $6, current_ifname, linenum); } | ID { $$ = new Func(NULL, NULL, $1, current_ifname, linenum); } | FORTRAN ID { $$ = new Func(NULL, NULL, $2, current_ifname, linenum); $$->fort = true; } | NEW ID { $$ = new Func(NULL, $2, mwrap_strdup("new"), current_ifname, linenum); } ; %% #include #include extern FILE* yyin; int yywrap() { return 1; } int yyerror(const char* s) { fprintf(stderr, "Parse error (%s:%d): %s\n", current_ifname.c_str(), linenum, s); return 0; } char* mwrap_strdup(const char* s) { char* result = new char[strlen(s)+1]; strcpy(result, s); return result; } const char* help_string = "mwrap 1.1 - MEX file generator for MATLAB and Octave\n" "\n" "Syntax:\n" " mwrap [-mex outputmex] [-m output.m] [-c outputmex.c] [-mb] [-list]\n" " [-catch] [-i8] [-c99complex] [-cppcomplex] infile1 infile2 ...\n" "\n" " -mex outputmex -- specify the MATLAB mex function name\n" " -m output.m -- generate the MATLAB stub called output.m\n" " -c outputmex.c -- generate the C file outputmex.c\n" " -mb -- generate .m files specified with @ redirections\n" " -list -- list files specified with @ redirections\n" " -catch -- generate C++ exception handling code\n" " -i8 -- convert int, long, uint, ulong to int64_t, uint64_t\n" " -c99complex -- add support code for C99 complex types\n" " -cppcomplex -- add support code for C++ complex types\n" "\n"; int main(int argc, char** argv) { int j; int err_flag = 0; init_scalar_types(); if (argc == 1) { fprintf(stderr, "%s", help_string); return 0; } else { for (j = 1; j < argc; ++j) { if (strcmp(argv[j], "-m") == 0 && j+1 < argc) outfp = fopen(argv[j+1], "w+"); if (strcmp(argv[j], "-c") == 0 && j+1 < argc) outcfp = fopen(argv[j+1], "w+"); if (strcmp(argv[j], "-mex") == 0 && j+1 < argc) mexfunc = argv[j+1]; if (strcmp(argv[j], "-mb") == 0) mbatching_flag = 1; if (strcmp(argv[j], "-list") == 0) listing_flag = 1; if (strcmp(argv[j], "-catch") == 0) mw_generate_catch = true; if (strcmp(argv[j], "-i8") == 0) mw_promote_int = 4; if (strcmp(argv[j], "-c99complex") == 0) mw_use_c99_complex = true; if (strcmp(argv[j], "-cppcomplex") == 0) mw_use_cpp_complex = true; } if (mw_use_c99_complex || mw_use_cpp_complex) { add_zscalar_type("dcomplex"); add_cscalar_type("fcomplex"); } for (j = 1; j < argc; ++j) { if (strcmp(argv[j], "-m") == 0 || strcmp(argv[j], "-c") == 0 || strcmp(argv[j], "-mex") == 0) ++j; else if (strcmp(argv[j], "-mb") == 0 || strcmp(argv[j], "-list") == 0 || strcmp(argv[j], "-catch") == 0 || strcmp(argv[j], "-i8") == 0 || strcmp(argv[j], "-c99complex") == 0 || strcmp(argv[j], "-cppcomplex") == 0); else { linenum = 1; type_errs = 0; yyin = fopen(argv[j], "r"); if (yyin) { current_ifname = argv[j]; if (outcfp) print_mex_init(outcfp); err_flag += yyparse(); fclose(yyin); } else { fprintf(stderr, "Could not read %s\n", argv[j]); } if (type_errs) fprintf(stderr, "%s: %d type errors detected\n", argv[j], type_errs); err_flag += type_errs; } } } if (!err_flag && outcfp) print_mex_file(outcfp, funcs); destroy(funcs); destroy_inherits(); if (outfp) fclose(outfp); if (outcfp) fclose(outcfp); return err_flag; } mwrap-1.1.1/src/stringify.c000066400000000000000000000017311430266125200156140ustar00rootroot00000000000000/* * stringify.c * Turns input from stdin into a C string definition written on * stdout. Adds quotes, newline characters, and backslashes as * needed. * * Copyright (c) 2007 David Bindel * See the file COPYING for copying permissions */ #include #include void stringify(const char* name) { char line[512]; char* p; printf("/*\n" " * Auto-generated by stringify\n" " */\n\n"); printf("const char* %s =", name); while (fgets(line, sizeof(line), stdin)) { printf("\n \""); for (p = line; *p; ++p) { if (*p == '"' || *p == '\\') putc('\\', stdout); if (*p != '\n' && *p != '\r') putc(*p, stdout); } printf("\\n\""); } printf(";\n\n"); } int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "String name required\n"); exit(-1); } stringify(argv[1]); return 0; } mwrap-1.1.1/testing/000077500000000000000000000000001430266125200143165ustar00rootroot00000000000000mwrap-1.1.1/testing/Makefile000066400000000000000000000050021430266125200157530ustar00rootroot00000000000000include ../make.inc all: test_transfers test_cpp_complex $(TESTC99COMPLEX) test_syntax \ test_typecheck test_catch test_fortran1 test_fortran2 \ test_redirect test_include test_single_cpp # run the tests... octave-cli --no-init-file --quiet test_all.m test_transfers: ../mwrap -mex test_transfersmex \ -c test_transfersmex.cc \ -m test_transfers.m test_transfers.mw $(MEX) test_transfersmex.cc test_cpp_complex: ../mwrap -cppcomplex \ -mex test_cpp_complexmex \ -c test_cpp_complexmex.cc \ -m test_cpp_complex.m test_cpp_complex.mw $(MEX) test_cpp_complexmex.cc test_c99_complex: ../mwrap -c99complex \ -mex test_c99_complexmex \ -c test_c99_complexmex.c \ -m test_c99_complex.m test_c99_complex.mw $(MEX) test_c99_complexmex.c # the following two are designed to create mwrap errors, and compared against # log files. For now, since they would break the make process, the minus signs # prevent them from being made. test_syntax: - ../mwrap -cppcomplex test_syntax.mw 2> test_syntax.log - diff test_syntax.log test_syntax.ref test_typecheck: - ../mwrap -cppcomplex test_typecheck.mw 2> test_typecheck.log diff test_typecheck.log test_typecheck.ref test_catch: ../mwrap -mex test_catchmex -catch \ -c test_catchmex.cc \ -m test_catch.m \ test_catch.mw $(MEX) test_catchmex.cc test_fortran1: ../mwrap -mex test_fortran1mex \ -c test_fortran1mex.cc \ -m test_fortran1.m \ test_fortran1.mw $(MEX) test_fortran1mex.cc test_fortran2: ../mwrap -mex test_fortran2mex \ -c test_fortran2mex.c \ -m test_fortran2.m \ test_fortran2.mw $(MEX) test_fortran2mex.c test_redirect: ../mwrap -mb test_redirect.mw test_include: ../mwrap -mex test_includemex\ -c test_includemex.cc \ -m test_include.m test_include.mw $(MEX) test_includemex.cc # these last two are tested by test_single.m ... test_single_cpp: ../mwrap -cppcomplex -mex test_singlemex \ -c test_singlemex.cc \ -mb test_single.mw $(MEX) test_singlemex.cc test_single_c99: ../mwrap -c99complex -mex test_singlemex \ -c test_singlemex.c \ -mb test_single.mw $(MEX) test_singlemex.c clean: rm -f *~ *.mex* *.o* test_typecheck.log rm -f test_fortran1.m test_fortran2.m test_transfers.m test_catch.m rm -f test_cpp_complex.m test_c99_complex.m rm -f test_transfersmex.cc test_catchmex.cc test_fortranmex.cc rm -f test_cpp_complexmex.cc test_c99_complexmex.c rm -f test_redirect.m test_redirect1.m rm -f test_singlemex.c test_singlemex.cc rm -f add.m addf.m addz.m addc.m rm -f arradd.m arraddf.m arraddz.m arraddc.m mwrap-1.1.1/testing/test_all.m000066400000000000000000000002541430266125200163040ustar00rootroot00000000000000test_transfers; test_cpp_complex; if exist('test_c99_complex.m'), test_c99_complex; end test_catch; test_fortran1; test_fortran2; test_redirect; test_include; test_single; mwrap-1.1.1/testing/test_c99_complex.mw000066400000000000000000000011201430266125200200470ustar00rootroot00000000000000function test_c99_complex; $ #include $ $ _Complex double zsum(_Complex double* zarray, int n) { $ int i; $ _Complex double sum = 0; $ for (i = 0; i < n; ++i) sum += zarray[i]; $ return sum; $ } zarray = rand(10,1) + 1i*rand(10,1); n = length(zarray); # dcomplex result = zsum(dcomplex[] zarray, int n); tassert(abs(result-sum(zarray)) < 1e-10*norm(zarray), 'C++ complex support'); # dcomplex cresult = conj(dcomplex result); tassert(conj(result) == cresult, 'C++ complex support (2)'); function tassert(pred, msg) if ~pred, fprintf('Failure: %s\n', msg); end mwrap-1.1.1/testing/test_catch.mw000066400000000000000000000003021430266125200167770ustar00rootroot00000000000000function test_catch $ void toss() $ { $ throw("Cookies"); $ } try # toss(); disp('Failed to properly catch exception'); catch fprintf('Correctly caught message: %s\n', lasterr); end mwrap-1.1.1/testing/test_cpp_complex.mw000066400000000000000000000011561430266125200202360ustar00rootroot00000000000000function test_cpp_complex; $ #include $ using std::complex; $ using std::conj; $ $ complex zsum(complex* zarray, int n) { $ complex sum(0); $ for (int i = 0; i < n; ++i) sum += zarray[i]; $ return sum; $ } zarray = rand(10,1) + 1i*rand(10,1); n = length(zarray); # dcomplex result = zsum(dcomplex[] zarray, int n); tassert(abs(result-sum(zarray)) < 1e-10*norm(zarray), 'C++ complex support'); # dcomplex cresult = conj(dcomplex result); tassert(conj(result) == cresult, 'C++ complex support (2)'); function tassert(pred, msg) if ~pred, fprintf('Failure: %s\n', msg); end mwrap-1.1.1/testing/test_fortran1.mw000066400000000000000000000004571430266125200174640ustar00rootroot00000000000000function test_fortran1 $ #ifdef __cplusplus $ extern "C" $ #endif $ int foo_(int* a, int* b, int* c) $ { $ *a = *b + *c; $ return(0); $ } # FORTRAN foo(output int* a, int 1, int 2); tassert(a == 3, 'FORTRAN bindings'); function tassert(pred, msg) if ~pred, fprintf('Failure: %s\n', msg); end mwrap-1.1.1/testing/test_fortran2.mw000066400000000000000000000004361430266125200174620ustar00rootroot00000000000000function test_fortran2 $ #ifdef __cplusplus $ extern "C" $ #endif $ int foo_(int* a, int* b, int* c) $ { $ *a = *b + *c; $ } # FORTRAN foo(output int* a, int 1, int 2); tassert(a == 3, 'FORTRAN bindings'); function tassert(pred, msg) if ~pred, fprintf('Failure: %s\n', msg); end mwrap-1.1.1/testing/test_include.mw000066400000000000000000000003421430266125200173440ustar00rootroot00000000000000function test_include() @include test_include2.mw tassert(j == 4, 'Include test'); % ================================================================ function tassert(pred, msg) if ~pred, fprintf('Failure: %s\n', msg); end mwrap-1.1.1/testing/test_include2.mw000066400000000000000000000000701430266125200174240ustar00rootroot00000000000000$int add2(int i) { return i+2; } # int j = add2(int 2); mwrap-1.1.1/testing/test_redirect.mw000066400000000000000000000002111430266125200175150ustar00rootroot00000000000000@function test_redirect if test_redirect1(42) ~= 42, fprint('Failure: Redirection failed?'); end @function x = test_redirect1(y) x = y; mwrap-1.1.1/testing/test_single.m000066400000000000000000000057611430266125200170250ustar00rootroot00000000000000function test_single % pass-fail test of the single- and double-precision args and arrays. % must do either make test_single_cpp or make test_single_c99 first. % Barnett & Gimbutas. 7/20/20 tol = 2e-16; tols = 1e-7; %format long g % for debug %fprintf('scalar real routines...\n') % ------------------------------------- x = 1/3; ce = x+x; xf = single(x); c = add(x,x); assert(abs(c-ce)tol) % test it's not doing double-prec! assert(class(c)=='single') %fprintf('\narray real routines...\n') % ------------------------------------ x = x*ones(3,1); xf = xf*ones(3,1); ce=x+x; c = arradd(x,x); assert(norm(c-ce)double, as mwrap 0.33.3 designed for! try c = arradd(xf,xf); % should error catch ME assert(ME.message=='test_singlemex: Invalid array argument, mxDOUBLE_CLASS expected'); end try c = arraddf(x,x); % should error catch ME assert(ME.message=='test_singlemex: Invalid array argument, mxSINGLE_CLASS expected'); end c = arraddf(xf,xf); % input as designed, should give single assert(norm(double(c)-ce)tol) % test it's not doing double-prec! assert(class(c)=='single') %fprintf('\nscalar complex routines...\n') % ------------------------------- z = (1+2i)/3; zf = single(z); ce = z+z; c = addz(z,z); assert(abs(c-ce)double, as mwrap 0.33.3 designed for! try c = addz(zf,zf); % should error catch ME assert(ME.message=='test_singlemex: Invalid scalar argument, mxDOUBLE_CLASS expected'); end try c = addc(z,z); % should error catch ME assert(ME.message=='test_singlemex: Invalid scalar argument, mxSINGLE_CLASS expected'); end c = addc(zf,zf); % input as designed, should give single assert(abs(double(c)-ce)tol) % test it's not doing double-prec! assert(class(c)=='single') % fprintf('\narray complex routines...\n') % -------------------------------- z = z*ones(3,1); zf = zf*ones(3,1); ce = z+z; c = arraddz(z,z); % input as designed, double assert(norm(c-ce)double, as mwrap 0.33.3 designed for! try c = arraddz(zf,zf); % should error catch ME assert(ME.message=='test_singlemex: Invalid array argument, mxDOUBLE_CLASS expected'); end try c = arraddc(z,z); % should error catch ME assert(ME.message=='test_singlemex: Invalid array argument, mxSINGLE_CLASS expected'); end c = arraddc(zf,zf); % input as designed, should give single assert(norm(double(c)-ce)tol) % test it's not doing double-prec! assert(class(c)=='single') mwrap-1.1.1/testing/test_single.mw000066400000000000000000000034751430266125200172140ustar00rootroot00000000000000% test double and single precision, scalars and arrays, in mwrap. % Barnett & Gimbutas 7/5/20-7/20/20. % make as in Makefile, % then pass-fail test in octave/matlab with: % test_single.m % the old non-pass-fail is here: % test_single_humanreadable.m % REAL====================================================== % scalar real......... $ void add(double a, double b, double *c) { *c = a + b; } @function c=add(a,b) # add(double a, double b, output double[1]c); $ void addf(float a, float b, float *c) { *c = a + b; } @function c=addf(a,b) # addf(float a, float b, output float[1]c); % array real........ $ void arradd(double *a, double *b, double *c, int n) $ { for (int i=0;idouble, as mwrap 0.33.3 designed for! try c = arradd(xf,xf) % should error catch ME ME.message disp('good') end try c = arraddf(x,x), class(c) % should error catch ME ME.message disp('good') end c = arraddf(xf,xf) % input as designed, should give single fprintf('\nscalar complex routines...\n') z = (1+2i)/3; zf = single(z); c = addz(z,z), class(c) try c = addz(zf,zf) % should error catch ME ME.message disp('good') end try c = addc(z,z), class(c) % should error catch ME ME.message disp('good') end c = addc(zf,zf) % input as designed, should give single fprintf('\narray complex routines...\n') z = z*ones(3,1); zf = zf*ones(3,1); try c = arraddz(z,z), class(c) % input as designed, double catch ME ME.message disp('****** bad') end try c = arraddz(zf,zf) % should error catch ME ME.message disp('good') end try c = arraddc(z,z), class(c) % should error catch ME ME.message disp('good') end try c = arraddc(zf,zf) % input as designed, should give single catch ME ME.message disp('****** bad') end mwrap-1.1.1/testing/test_syntax.mw000066400000000000000000000003071430266125200172500ustar00rootroot00000000000000 function badmojo # double z = sumpair(double x) // Missing semicolon should result in error // Another line just to double check lines # double z = sumpair(double x); # double z = sumpair(double x) mwrap-1.1.1/testing/test_syntax.ref000066400000000000000000000002401430266125200173750ustar00rootroot00000000000000Parse error (test_syntax.mw:4): syntax error, unexpected NON_C_LINE, expecting ';' Parse error (test_syntax.mw:8): syntax error, unexpected $end, expecting ';' mwrap-1.1.1/testing/test_transfers.mw000066400000000000000000000361511430266125200177370ustar00rootroot00000000000000function test_transfers test_mult_inherit; test_scopes; test_literals; test_types; test_complex; test_nulls; test_method; test_returns; test_inputs; test_outputs; test_inouts; test_mx; test_const; test_struct; % ================================================================ $[ #include #include struct Pair { Pair(double x, double y) { xy[0] = x; xy[1] = y; } double xy[2]; double x() { return xy[0]; } double y() { return xy[1]; } }; struct BadPair { double x; }; struct DerivedPair : public Pair { DerivedPair() : Pair(7,11) {} }; #include typedef std::complex cmplx; #define real_cmplx(z) (z).real() #define imag_cmplx(z) (z).imag() #define setz_cmplx(zp, r, i) *zp = cmplx(r,i) typedef unsigned char uchar; typedef unsigned long ulong; $] % ================================================================ function test_mult_inherit $[ class Parent1 { public: Parent1(int data) : data1_(data) {} virtual ~Parent1() {} virtual int data1() { return data1_; } protected: int data1_; }; class Parent2 { public: Parent2(int data) : data2_(data) {} virtual ~Parent2() {} virtual int data2() { return data2_; } protected: int data2_; }; class Child : public Parent1, public Parent2 { public: Child() : Parent1(1), Parent2(2) {} virtual int data1() { return data1_ + 1; } virtual int data2() { return data2_ + 1; } int datas() { return data1_ + data2_; } }; $] # class Child : Parent1, Parent2; # Child* c = new Child(); # int d1 = c->Parent1.data1(); # int d2 = c->Parent2.data2(); # int dd = c->Child.datas(); tassert(d1 == 2, 'Multiple inheritance handling (1)'); tassert(d2 == 3, 'Multiple inheritance handling (2)'); tassert(dd == 3, 'Multiple inheritance handling (3)'); % ================================================================ function test_scopes; $ class OuterClass { $ public: $ static int static_method() { return 123; } $ }; # int x = OuterClass::static_method(); tassert(x == 123, 'Access to static class method'); % ================================================================ function test_literals; $ int literal_plus1(int x) { return x+1; } # int y = literal_plus1(int 7); # int l = strlen(cstring 'Test'); tassert(y == 8, 'Integer literals'); tassert(l == 4, 'String literals'); % ================================================================ function test_types; $ typedef unsigned char byte; $ void takes_double(double& x) {} $ void takes_float(float& x) {} $ void takes_long(long& x) {} $ void takes_int(int& x) {} $ void takes_char(char& x) {} $ void takes_ulong(unsigned long& x) {} $ void takes_uint(unsigned int& x) {} $ void takes_uchar(unsigned char& x) {} $ void takes_bool(bool& x) {} $ void takes_size_t(size_t& x) {} x = 0; xs = single(x); # typedef numeric byte; # takes_double(double& x); # takes_float(float& xs); # takes_long(long& x); # takes_int(int& x); # takes_char(char& x); # takes_ulong(ulong& x); # takes_uint(uint& x); # takes_uchar(uchar& x); # takes_uchar(byte& x); # takes_bool(bool& x); # takes_size_t(size_t& x); # class DerivedPair : Pair; # DerivedPair* dp = new DerivedPair(); # double x = dp->Pair.x(); tassert(x == 7, 'Type casting'); % ================================================================ function test_complex; $ cmplx zsum(cmplx* zarray, int n) { $ cmplx sum(0); $ for (int i = 0; i < n; ++i) sum += zarray[i]; $ return sum; $ } zarray = rand(10,1) + 1i*rand(10,1); n = length(zarray); # typedef dcomplex cmplx; # cmplx result = zsum(cmplx[] zarray, int n); tassert(abs(result-sum(zarray)) < 1e-10*norm(zarray), 'Complex support'); % ================================================================ function test_nulls; $ Pair* null_pair() { return NULL; } # Pair* p = null_pair(); tassert(p == 0, 'Null pointer return'); $ int is_null(Pair* p) { return !p; } # int flag = is_null(Pair* p); tassert(flag, 'Null pointer input'); $ char* null_string() { return NULL; } # cstring s = null_string(); tassert(s == 0, 'Null string return'); # char* c = null_string(); tassert(isempty(c), 'Null scalar pointer return'); nil = []; $ int is_null(double* data) { return !data; } # int flag = is_null(double[] nil); tassert(flag, 'Null array input'); # char[1] ca = null_string(); tassert(isempty(ca), 'Null array return'); $ void test_null_obj(Pair& p) { } try # test_null_obj(Pair p); tassert(0, 'Null argument dereference 1'); end try # test_null_obj(Pair& p); tassert(0, 'Null argument dereference 1'); end try # double x = p->Pair.x(); tassert(0, 'Invalid this test'); end # BadPair* bp = new BadPair(); try $ void test_bad_pair(Pair* p) { } # test_bad_pair(Pair* bp); tassert(0, 'Invalid pointer test'); end # delete(BadPair* bp); % ================================================================ function test_method; x = 1; y = 2; # Pair* p = new Pair(double x, double y); # double xx = p->Pair.x(); # double yy = p->Pair.y(); # delete(Pair* p); tassert(xx == 1, 'Method call'); tassert(yy == 2, 'Method call'); % ================================================================ function test_returns; $ Pair test_return_obj() { return Pair(1.5, 2.5); } # Pair p1 = test_return_obj(); tassert(sscanf(p1, 'Pair:%x') > 0, 'Return object'); $ double* test_return_array(Pair& p) { return p.xy; } # double[2] xy = test_return_array(Pair& p1); tassert(norm(xy-[1.5; 2.5]) == 0, 'Return array'); $ double* test_return_array2(Pair& p) { return p.xy; } # double xy[2] = test_return_array2(Pair& p1); tassert(norm(xy-[1.5; 2.5]) == 0, 'Return array'); $ double test_return_scalar(double* xy) { return xy[0] + xy[1]; } # double sum = test_return_scalar(double[] xy); tassert(sum == 4, 'Return scalar'); xy_z = [1+5i, 7+11i]; $ cmplx test_return_zscalar(cmplx* xy) { return xy[0] + xy[1]; } # cmplx sum1 = test_return_zscalar(cmplx[] xy); # cmplx sum2 = test_return_zscalar(cmplx[] xy_z); tassert(sum1 == 4, 'Return zscalar (reals)'); tassert(sum2 == 8+16i, 'Return zscalar (complexes)'); $ const char* test_return_string() { return "Hello, world!"; } # cstring s = test_return_string(); tassert(strcmp(s, 'Hello, world!'), 'Return string'); $ Pair* test_return_p_obj() { return new Pair(3, 5); } # Pair* p2 = test_return_p_obj(); # double[2] xy = test_return_array(Pair& p2); tassert(norm(xy - [3;5]) == 0, 'Return obj*'); a = 7; b = 11; $ int* test_return_p_scalar(int* a, int* b) { return (*a > *b) ? a : b; } # int* z1 = test_return_p_scalar(int* a, int* b); tassert(z1 == 11, 'Return scalar*'); a_z = 7 + 10i; b_z = 11 + 15i; $ cmplx* test_return_p_zscalar(cmplx* a, cmplx* b) { $ return (a->real() > b->real()) ? a : b; $ } # cmplx* z1 = test_return_p_zscalar(cmplx* a, cmplx* b); # cmplx* z2 = test_return_p_zscalar(cmplx* a_z, cmplx* b_z); tassert(z1 == 11, 'Return zscalar*'); tassert(z2 == 11 + 15i, 'Return zscalar*'); $ Pair& test_return_r_obj(Pair& p) { return p; } # Pair& p2c = test_return_r_obj(Pair& p2); tassert(strcmp(p2, p2c), 'Return obj&'); $ int& test_return_r_scalar(int& a, int& b) { return (a > b) ? a : b; } # int& z2 = test_return_r_scalar(int& a, int& b); tassert(z2 == 11, 'Return scalar&'); $ cmplx& test_return_r_zscalar(cmplx& a, cmplx& b) { $ return (a.real() > b.real()) ? a : b; $ } # cmplx& z2 = test_return_r_zscalar(cmplx& a, cmplx& b); # cmplx& z3 = test_return_r_zscalar(cmplx& a_z, cmplx& b_z); tassert(z2 == 11, 'Return zscalar&'); tassert(z3 == 11 + 15i, 'Return zscalar&'); # delete(Pair* p1); # delete(Pair* p2); % ================================================================ function test_inputs x = 101; y = 202; # Pair* p = new Pair(double x, double y); $ double test_input_obj(Pair p) { return p.xy[0] + p.xy[1]; } # double sum = test_input_obj(input Pair p); tassert(sum == 303, 'Input obj'); xy = [11, 22]; $ double test_input_array(double* xy) { return xy[0] + xy[1]; } # double sum = test_input_array(double[2] xy); tassert(sum == 33, 'Input array'); $ double test_input_array2(double* xy) { return xy[0] + xy[1]; } # double sum = test_input_array2(double xy[2]); tassert(sum == 33, 'Input array'); xy_z = [11 + 5i, 22 + 6i]; $ cmplx test_input_zarray(cmplx* xy) { return xy[0] + xy[1]; } # cmplx sum = test_input_zarray(cmplx[2] xy); # cmplx sum2 = test_input_zarray(cmplx[2] xy_z); tassert(sum == 33, 'Input zarray'); tassert(sum2 == 33 + 11i, 'Input zarray'); $ int test_input_scalar(int x) { return x+1; } # int xp1 = test_input_scalar(int x); tassert(xp1 == 102, 'Input scalar'); x_z = 101 + 99i; $ cmplx test_input_zscalar(cmplx x) { return x+1.0; } # cmplx xp1 = test_input_zscalar(cmplx x); # cmplx xp1z = test_input_zscalar(cmplx x_z); tassert(xp1 == 102, 'Input zscalar'); tassert(xp1z == 102 + 99i, 'Input zscalar'); msg = 'Hello, world!'; $ int test_input_string(char* s) { return strlen(s); } # int msglen = test_input_string(cstring msg); tassert(msglen == length(msg), 'Input string'); $ double test_input_p_obj(Pair* p) { return p->xy[0] + p->xy[1]; } # double sum2 = test_input_p_obj(Pair* p); tassert(sum2 == 303, 'Input obj*'); $ int test_input_p_scalar(int* x) { return *x+1; } # int xp1b = test_input_p_scalar(int* x); tassert(xp1b == 102, 'Input scalar*'); $ cmplx test_input_p_zscalar(cmplx* x) { return *x+1.0; } # cmplx xp1b = test_input_p_zscalar(cmplx* x); # cmplx xp1c = test_input_p_zscalar(cmplx* x_z); tassert(xp1b == 102, 'Input zscalar*'); tassert(xp1c == 102 + 99i, 'Input zscalar*'); $ double test_input_r_obj(Pair& p) { return p.xy[0] + p.xy[1]; } # double sum3 = test_input_r_obj(Pair& p); tassert(sum3 == 303, 'Input obj&'); $ int test_input_r_scalar(int& x) { return x+1; } # int xp1c = test_input_r_scalar(input int& x); tassert(xp1c == 102, 'Input scalar&'); $ cmplx test_input_r_zscalar(cmplx& x) { return x+1.0; } # cmplx xp1c = test_input_r_zscalar(input cmplx& x); # cmplx xp1d = test_input_r_zscalar(input cmplx& x_z); tassert(xp1c == 102, 'Input scalar&'); tassert(xp1d == 102 + 99i, 'Input scalar&'); # delete(input Pair* p); % ================================================================ function test_outputs $ void test_output_array(double* xy) { xy[0] = 1; xy[1] = 2; } # test_output_array(output double[2] xy); tassert(norm(xy-[1;2]) == 0, 'Output array'); $ void test_output_rarray(const double*& xy) { $ static double result[2] = {7, 11}; $ xy = result; $ } # test_output_rarray(output double[2]& xyr); tassert(norm(xyr-[7;11]) == 0, 'Output rarray'); $ void test_output_rarray2(const double*& xy) { xy = NULL; } # test_output_rarray2(output double[2]& xyr2); tassert(isempty(xyr2), 'Output rarray'); $ void test_output_zarray(cmplx* xy) { xy[0] = 1; xy[1] = 2; } $ void test_output_zarray2(cmplx* xy) { xy[0] = cmplx(1,3); xy[1] = 2; } # test_output_zarray(output cmplx[2] xy); # test_output_zarray2(output cmplx[2] xy_z); tassert(norm(xy-[1;2]) == 0, 'Output array'); tassert(norm(xy_z-[1+3i;2]) == 0, 'Output array'); fmt = '= %d'; i = 101; # sprintf(output cstring[128] buf, input cstring fmt, input int i); tassert(strcmp('= 101', buf), 'Output string'); $ void test_output_p_scalar(int* i) { *i = 202; } # test_output_p_scalar(output int* i2); tassert(i2 == 202, 'Output scalar*'); $ void test_output_p_zscalar(cmplx* z) { *z = cmplx(202,303); } # test_output_p_zscalar(output cmplx* z2); tassert(z2 == 202+303i, 'Output zscalar*'); $ void test_output_r_scalar(int& i) { i = 303; } # test_output_r_scalar(output int& i3); tassert(i3 == 303, 'Output scalar&'); $ void test_output_r_zscalar(cmplx& z) { z = cmplx(303,404); } # test_output_r_zscalar(output cmplx& z3); tassert(z3 == 303+404i, 'Output zscalar&'); % ================================================================ function test_inouts xy = [1, 2]; $ void test_inout_array(double* xy) { xy[0] += 1; xy[1] += 1; } # test_inout_array(inout double[] xy); tassert(norm(xy - [2,3]) == 0, 'Inout array'); s1 = 'foo'; s2 = 'bar'; # strcat(inout cstring[128] s1, input cstring s2); tassert(strcmp(s1, 'foobar'), 'Inout string'); i1 = 101; $ void test_inout_p_scalar(int* i) { *i += 202; } # test_inout_p_scalar(inout int* i1); tassert(i1 == 303, 'Inout scalar*'); i2 = 101; $ void test_inout_r_scalar(int& i) { i += 303; } # test_inout_r_scalar(inout int& i2); tassert(i2 == 404, 'Inout scalar&'); % ================================================================ function test_mx $ #include in1 = 42; $ double test_mx_input(const mxArray* x) { return *mxGetPr(x); } # double out1 = test_mx_input(input mxArray in1); tassert(out1 == 42, 'Input mx'); $ void test_mx_output(mxArray** x) $ { $ *x = mxCreateString("foobar"); $ } # test_mx_output(output mxArray out2); tassert(strcmp(out2, 'foobar'), 'Output mx'); $ mxArray* test_mx_return() $ { $ mxArray* m = mxCreateDoubleMatrix(1,1, mxREAL); $ *mxGetPr(m) = 42; $ return m; $ } # mxArray out3 = test_mx_return(); tassert(out3 == 42, 'Return mx'); % ================================================================ function test_const $ const int TEST_CONST = 42; $ int identity(int i) { return i; } # int result = identity(const TEST_CONST); tassert(result == 42, 'Constant transfer'); # int result2 = identity(const 'TEST_CONST'); tassert(result2 == 42, 'Constant transfer'); % ================================================================ function test_struct $[ struct my_struct_t { double x; double y; }; int my_struct_allocs = 0; int get_my_struct_allocs() { return my_struct_allocs; } my_struct_t* mxWrapGet_my_struct_t(const mxArray* a, const char** e) { // Note -- there really ought to be an error check here ++my_struct_allocs; my_struct_t* o = new my_struct_t; o->x = mxGetPr(a)[0]; o->y = mxGetPr(a)[1]; return o; } mxArray* mxWrapSet_my_struct_t(my_struct_t* o) { mxArray* a = mxCreateDoubleMatrix(2,1,mxREAL); mxGetPr(a)[0] = o->x; mxGetPr(a)[1] = o->y; return a; } my_struct_t* mxWrapAlloc_my_struct_t() { ++my_struct_allocs; return new my_struct_t; } void mxWrapFree_my_struct_t(my_struct_t* o) { --my_struct_allocs; delete o; } void unpack_struct(my_struct_t& o, double* xy) { xy[0] = o.x; xy[1] = o.y; } void pack_struct(my_struct_t& o, double* xy) { o.x = xy[0]; o.y = xy[1]; } void swap_struct(my_struct_t& o) { double tmp = o.x; o.x = o.y; o.y = tmp; } my_struct_t& rightmost(my_struct_t& p1, my_struct_t& p2) { return (p1.x >= p2.x) ? p1 : p2; } my_struct_t* add1(my_struct_t& o) { o.x += 1; o.y += 1; return &o; } $] # typedef mxArray my_struct_t; xy1 = [1, 2]; # unpack_struct(my_struct_t& xy1, output double xy2[2]); tassert(norm(xy2-[1;2]) == 0, 'Structure conversion on input'); # pack_struct(output my_struct_t xy3, double[] xy1); tassert(norm(xy3-[1;2]) == 0, 'Structure conversion on output'); xy4 = [3; 4]; # swap_struct(inout my_struct_t xy4); tassert(norm(xy4-[4; 3]) == 0, 'Structure on inout'); # my_struct_t& result = rightmost(my_struct_t& xy1, my_struct_t& xy4); tassert(norm(result-[4;3]) == 0, 'Structure on reference return'); # my_struct_t* xy5 = add1(my_struct_t& xy4); tassert(norm(xy5-[5;4]) == 0, 'Structure on pointer return'); # int alloc_count = get_my_struct_allocs(); tassert(alloc_count == 0, 'Balanced allocations in structure management'); % ================================================================ function tassert(pred, msg) if ~pred, fprintf('Failure: %s\n', msg); end mwrap-1.1.1/testing/test_typecheck.mw000066400000000000000000000012371430266125200177040ustar00rootroot00000000000000 function badmojo # double z = sumpair(inout Pair p); # double z = sumpair(output Pair p); # dble(inout int y); # dble(output int y); # strcat(inout cstring s1, cstring s2); # strcat(output cstring s1, cstring s2); # double z = sumpair(inout Pair& p); # double z = sumpair(inout Pair* p); # double z = sumpair(output Pair& p); # double z = sumpair(output Pair* p); # get34(output int[] z); # get34(output fcomplex[] z); # get34(output dcomplex[] z); # get(output int[1,2,3] z); # typedef bozo byte; %# An okay line -- should be ignored, since it doesn't start with # # // Another okay line -- comments should be ignored // Another okay line -- comments should be ignored mwrap-1.1.1/testing/test_typecheck.ref000066400000000000000000000011761430266125200200370ustar00rootroot00000000000000Error (3): Object p cannot be output Error (4): Object p cannot be output Error (5): Scalar y cannot be output Error (6): Scalar y cannot be output Error (7): String s1 cannot be output without size Error (8): String s1 cannot be output without size Error (9): Object p cannot be output Error (10): Object p cannot be output Error (11): Object p cannot be output Error (12): Object p cannot be output Error (13): Output array z must have dims Error (14): Output array z must have dims Error (15): Output array z must have dims Error (16): Array z should be 1D or 2D Unrecognized typespace: bozo test_typecheck.mw: 15 type errors detected