mwrap-0.33/COPYING0000600001174600117460000000232411133213513013402 0ustar dbindeldbindelmwrap -- 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-0.33/Makefile0000600001174600117460000000035111133213513014005 0ustar dbindeldbindelinclude 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-0.33/NEWS0000600001174600117460000000431011133213513013043 0ustar dbindeldbindelRecent updates: 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-0.33/README0000600001174600117460000000132411153601104013225 0ustar dbindeldbindelmwrap-0.33 (http://www.cims.nyu.edu/~dbindel/mwrap/) 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. To compile, edit make.inc and then run make. The output will be a standalone executable (mwrap) in the main directory. The 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. mwrap-0.33/doc/mwrap.tex0000600001174600117460000007320111133213513014766 0ustar dbindeldbindel\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} \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] [-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 -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 typdef numeric} {\it type-id} {\tt ;} \\ & {\tt typdef dcomplex} {\it type-id} {\tt ;} \\ & {\tt typdef 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}, 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 uint32\_t} as a numeric type, we would need the line \begin{verbatim} # typedef numeric uint32_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} \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 (I think). \item {\tt -DMWF77\_UNDERSCORE1} -- Append a single underscore to an all-lower-case name. Used by the Intel FORTRAN compiler. \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-0.33/example/Makefile0000600001174600117460000000034111133213513015437 0ustar dbindeldbindelall: (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-0.33/example/eventq/Makefile0000600001174600117460000000070611133213513016746 0ustar dbindeldbindelinclude ../../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-0.33/example/eventq/README0000600001174600117460000000136211133213513016165 0ustar dbindeldbindelExample 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-0.33/example/eventq/eventq_class.mw0000600001174600117460000000275611133213513020351 0ustar dbindeldbindel% 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-0.33/example/eventq/eventq_handle.mw0000600001174600117460000000262011133213513020465 0ustar dbindeldbindel% 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-0.33/example/eventq/eventq_plain.mw0000600001174600117460000000206711133213513020342 0ustar dbindeldbindel% 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-0.33/example/eventq/testq_class.m0000600001174600117460000000066711133213513020017 0ustar dbindeldbindel% 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-0.33/example/eventq/testq_handle.m0000600001174600117460000000071111133213513020133 0ustar dbindeldbindel% 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-0.33/example/eventq/testq_plain.m0000600001174600117460000000062411133213513020006 0ustar dbindeldbindel% 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-0.33/example/eventq2/Makefile0000600001174600117460000000025711133213513017031 0ustar dbindeldbindelinclude ../../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-0.33/example/eventq2/README0000600001174600117460000000046311133213513016250 0ustar dbindeldbindelExample 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-0.33/example/eventq2/eventq2.mw0000600001174600117460000000235311133213513017321 0ustar dbindeldbindel% 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-0.33/example/eventq2/testq2.m0000600001174600117460000000065011133213513016766 0ustar dbindeldbindel% 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-0.33/example/fem/Makefile0000600001174600117460000000025711133213513016214 0ustar dbindeldbindelall: 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-0.33/example/fem/README0000600001174600117460000000070711133213513015434 0ustar dbindeldbindelThis 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-0.33/example/fem/init.m0000600001174600117460000000006211133213513015667 0ustar dbindeldbindelif ~exist('femex'), addpath([pwd, '/mwfem']); end mwrap-0.33/example/fem/interface/Makefile0000600001174600117460000000033011133213513020144 0ustar dbindeldbindelinclude ../../../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-0.33/example/fem/interface/assembler.mw0000600001174600117460000000415211133213513021034 0ustar dbindeldbindel% 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-0.33/example/fem/interface/elements.mw0000600001174600117460000000202711133213513020672 0ustar dbindeldbindel% 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-0.33/example/fem/interface/mesh.mw0000600001174600117460000002025111133213513020011 0ustar dbindeldbindel% 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-0.33/example/fem/src/Makefile0000600001174600117460000000067611133213513017010 0ustar dbindeldbindel# 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-0.33/example/fem/src/assembler.cc0000600001174600117460000000600711153571774017650 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/assembler.h0000600001174600117460000000510711133213513017470 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/assembler2.cc0000600001174600117460000000601011153572043017712 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/assembler2.h0000600001174600117460000000511211133213513017546 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/elastic2d.cc0000600001174600117460000000730511153572627017545 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/elastic2d.h0000600001174600117460000000137011133213513017363 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/elastic2d1.cc0000600001174600117460000002501111153572621017612 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/etype.h0000600001174600117460000000100011133213513016625 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/feintegrals.h0000600001174600117460000000211011133213513020005 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/feshapes.h0000600001174600117460000000106211133213513017305 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/gauss2by2.cc0000600001174600117460000000071511133213513017472 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/gauss2by2.h0000600001174600117460000000130711133213513017332 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/mesh.cc0000600001174600117460000000420411133213513016602 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/mesh.h0000600001174600117460000000653411133213513016454 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/quad2d.cc0000600001174600117460000000255311133213513017033 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/quad2d.h0000600001174600117460000000130111133213513016663 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/quad2d1.cc0000600001174600117460000001360611133213513017115 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/scalar1d.cc0000600001174600117460000000205011133213513017335 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/scalar1d.h0000600001174600117460000000102211133213513017175 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/scalar2d.cc0000600001174600117460000000335311133213513017345 0ustar dbindeldbindel/* * 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-0.33/example/fem/src/scalar2d.h0000600001174600117460000000116211133213513017203 0ustar dbindeldbindel/* * 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-0.33/example/fem/test_assembler.m0000600001174600117460000000222511133213513017743 0ustar dbindeldbindel% 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-0.33/example/fem/test_patch.m0000600001174600117460000000314411133213513017066 0ustar dbindeldbindel% 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-0.33/example/fem/test_simple.m0000600001174600117460000000174711133213513017267 0ustar dbindeldbindel% 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-0.33/example/foobar/Makefile0000600001174600117460000000027611133213513016716 0ustar dbindeldbindelinclude ../../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-0.33/example/foobar/foobar.mw0000600001174600117460000000024611133213513017070 0ustar dbindeldbindel$ #include function foobar; s1 = 'foo'; s2 = 'bar'; # strncat(inout cstring[128] s1, cstring s2, int 127); fprintf('Should be foobar: %s\n', s1); mwrap-0.33/example/zlib/Makefile0000600001174600117460000000030511133213513016377 0ustar dbindeldbindel# 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-0.33/example/zlib/README0000600001174600117460000000031111133213513015614 0ustar dbindeldbindelThis 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-0.33/example/zlib/gzfile.mw0000600001174600117460000000262511133213513016573 0ustar dbindeldbindel% 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-0.33/example/zlib/testgz.m0000600001174600117460000000065111133213513016441 0ustar dbindeldbindel% 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-0.33/make.inc0000600001174600117460000000103311153600677013770 0ustar dbindeldbindel# === 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= gcc 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-0.33/mwrap.pdf0000600001174600117460000035712311153601104014201 0ustar dbindeldbindel%PDF-1.4 3 0 obj << /Length 2037 /Filter /FlateDecode >> stream xÚ•ÛnÛ6ô½_a *£1'^$‘ÙV Íº¡Cû´ °îA‘éX˜mº,Íßï\HYŽ5,{IÈ£sç¹úÝí‹o~”ÅB¥"ÏU¶¸Ý,”Ì…Ò¦X©EfôâvýGòé·¥LÚåJ&åqùçíÏ@•O©l.d–©EJØ¿vˆé_§*ùi¨×>Ù…4B›\!ÑJešÂ,V:ÆÁG$þA™Ê“wÈ£>¬A°ÇãY,V@¯ŒR@lEj@OR¯l«¥*’-“ ¹Âc‘(8¦©cñÊ,d!”Ì ‰—.:Mõb•¥¢ÐV/ ¤ʒ@yXj™ôm¼d²ª`uCØžb!¥ph90LA)pž5öß|f§èÆ '³"ø¬îÐ[6)‰;ëÃRÙ¤÷í¦¬<ƒî£7¾EÌ>hC»Ç®÷û‘þI¿õ| '9Ö-ZÐ3’nøøËo~:[>îIúõ„áeŒrÉK‹82iöÌ»œˆð=_š ¿W´ΘŒ]ShÈÞyï×KxÍ4ù„ôo—V%·ß¾C˜Lºª­=ÿœJ³óÝÕœïeg[dÁ›Ïð}†ÇØõnÇâÈ¿èÛÞ³Ì2¨öyýÎD„T¾Ä'zdbŒŽ†QÖžœAî¦÷ &Þ|só@¯Ù7JI‘NŸ;g3*xW|@©“ŠŒšÝ#Dš¤„œ Ã§‰¯´Ì"a@ãKß0òªH£.·üÌt™1 Dà»CÜ"Å`®}tuÔªÙðÿª¡¨ý9ø¶¯÷dkmtd#)ƒî%[Àw›1žà Cqü–JÁ«Ž?®IÝ’/]t9 Ý?´+í2N¤À”³ÑøFER•¤ÜTÓC›\äGÈ«#Q5” í#ƒ»(—Á÷þêÜØí!Ö£m½^û—©QÙ NVÀ:ߊù0¸ðŒýƺ… t.Äú j¹"Oš¿ðj’]ý¾ç3¯€`ÎÈŽ)ê~Ë'®/ä#_Õån÷Èð ”}Ù£›(Ó‡ÿ‚·¶Œb>ðƒ`ìù‚î˜!§Kž SØ'ÖW%'†Î8¨àL2 Û\a¹Rð@üÍÁßwÃD[z=r»†iv •<~{ ©8^Öž¯T¨¹âDƒ/1Ö'¹Nˆ\ݸ(   üJ¬6S…§:Ü„V•Ÿ=¡2ÂébÙÛ7sÁ¿"u¨X֚¢¹£dú–褂f¬5vë$7öN2ú÷üïv¬I_};'¬Sèw”}óè/mêN<~N³”Ìj®ŒˆTux>™û‡ÄÑÂþXÀY^ÍaŽŸUø\"Ó f €,RΪ¸9ŽNFÕ6¨šõËý7`¼®™ï?ó,†y{Í ¯áÒ}–ç¢Ã««‰Ê£Ü‹ð9=EDNÚÜn}‹qêŠSQsE˜ð´Ë±,ð4L»‚«f{~Ç”4¦8¬|u€p}‚ÔÍMŽòŠ%‚O¡"Üׇg(PSš‰gm3­ ióÕœ¡2…h3qrí=V“™Â £j. ûÌñ’OŠ"OÍùcŽ­Vi0Y2‡°Ç‚RiŽ¡¡äÀb¬LW8]¨±å! ê%ˆ¹Ë‰ë¼‡4©P šu¢.„3YtâË9{Ð6ÆÀÊ;ÛXÀqà`qeЪ 9¢‰ Ï–Àì$B+÷d’|N)4Ð7¬ŽÄ HÃìd¨Q6g< ¡lj êCEº•Åè»Û©¼_jèÔG 7áŽIðxŒÎ!PÃÿï¦@Ö|¢a‡sž«ƒQçc‹Á½éÈ¢%'êý0&ÆŠ #Š3QÇܧ³ë©ûvŒHq²ÅRw-Œ¹#•ðrïÇö‡òºS@¶žÏѬàí¥–1t­œšJ÷f@Þ€*¸QÌÌ@Ôã[š£`Äí±8Öa0 B´T¡¶ ÷ù"…í­Pæù;„³2îoÇ6$ã@Âé± ÚœUGPì9qæÖ§‰L&ד–øp3ýÎç‡m=.ºx¥ÅOcÔð ŽÛÕ±ÞÇyi.´°RËs§ñðË4Ç &+ÅLÊ4Yêb¢ï=ˆù2ç¥aŸwÑ‘œFwJz|h”V^¥{ ?|ôžA»ñ†>V=ÔTâôþw>Œ]¤€Ë‡ÍÉJv‡r"MíÓ¥4¦í¸¾pwýýª›ó ¦Zæ2˜Iƹhÿ0ç¢,:/¢‹Ð9Ô»[–é¿ÄÁ£6c AiÙ­rñ›@ìÐaä6FÑ1C7q¯¬ü´ñΙ§rÒ±\Ø7kž†cÌ ^¯>>×.mEfN9ÌÅ‹·Ÿ°óÏ9¸»ðæŽ~DÀ tšÅÌ •±È1¶lñú1×r$ Nfú|,†÷¤Ý…Öœ¤V!xüºÛ£›Ãm…zñ¬·A¯5ãD*öŸÀO£åéøeV'™á›e)Uî¹2Ï$võüyñ-‡]ð7Ud8aÛãšB\^1| sÚÎCô™Vüp9|Q™ Þln²¹+Ý)–Ãü¬>…¼½XÆÏ~f;Vz,¯ýõ|ÐXðDaÔyмy3}î3?Œ„¹{òÓ¹þüÑ®ã´ÏÌâ`pQ‰¥…AÔå Ö.üÆ ¨/Þß¾øÛ…^ÿendstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 19 0 R >> endobj 1 0 obj << /Font << /F17 6 0 R /F16 9 0 R /F18 12 0 R /F24 15 0 R /F26 18 0 R >> /ProcSet [ /PDF /Text ] >> endobj 22 0 obj << /Length 2395 /Filter /FlateDecode >> stream xÚÕYK“Û6¾ûWè¶T%‚ñ$ÁäÛ•ÝÊV¼9döQåøÀ!©cŠTñ‘™ù÷ÛHQCÅŠsÊL•‚F?¾~z{÷êõßE²‚¥ÆÈÍÝ~#­dÖr¹IRÃøÛÜ¢÷ÿÝŠ¨ÛîD”¶ïþùêû»WbÃá_l µ)Kuj6ùñNêØnÓ©Ö›®Üì'ÒÐîΉß:ì¹ðÖ˜t“˜„ñDZ·ý¶VF%nß=ªF u’D8ÞÓðÿú7âè§|ȶÒF¿me‚kq®+ë2ëË‚H3\5”=+x,vÈ[ˆóç í6žNÛ¤º˜‘ñ˜ãçfÚ=}¿Ç%oPæ»ß¼ý›òý÷ÿCÓmv"qî„fZÒ°j³G©r§+Ûîl¬£Ÿ«ã©.q饯҄Ie%˜vÍG—†Õ1P§±§Þ=”MÙe¬q›¡Mâ4Ê[§gá Æ£þ€uAÛ`ƒODþè\LDAæ‡7Kó{Uî¶VÀz¿ÓñT‘^h ÅÀFvi”}‹¾ÑÂs…Á’ë×´çØ{ëÈø\_v‰µ^áã'²ÍácØÃn½3BG;xØKø|Z³ZŠÎÒÊ3©š~(³‚„qî†oòÝo(Wû©jV…ášYpVæê~Â2mL »%–_ÓŸæ rY‰0Ó2jÐ?™U)˸I0kJJ žŽ%!Ö¦€Ø7虀V™’—ïÁB&úµÌ=Õ1€£Ë+.)6ZzC€BÃ!s¢¸×££-{¿ß‹y¹çŽ˜Ø*/+.®ÞgyUWCÜPM¾DÍcU× ,hÐãŽaÍØäȱZµ M>VÃH…qê·äK½0Ia4ºöS”ŠÝ~Ø i0þRu|;yð [³¦ ç7nÊ5ŸC Ái5)pwXųԌÇ2 ñøˆ–A¯»Ò,Ž![1ÈrDR' èU£ NÝCÖÓ`8”ôn&¯ëõD4“ùZ̼ÇoÖƒpfZrHï ¢æÖ¼ÐÚ‡¤|¢§vDlœ0» KŽ0/¢3%…×'÷ÉŽÆD0lós² ^,_2h}tpQ1K…ˆ— ù€i ÆÐ/6Œ:àç!°sÓ)|¦8 ‰ »ž6Ä,ŽÓ§¥[P¬`¶B¨î«@$h{|nB²Â²äx3†Ú­9}§S©Y:âñPvP‹òÖ J´§ÖŽú.’õlʬâSõð®\BZÛ$$°žê¦+1yÌ5¦i‹‡ +s>£_Éq誊ŸÆÚéÆÕþÀ& ED• á… Ã-ŸRÍ .”BvAêE¢ô™$b•Õ5äb“B’DUj‘XÞI$3ñÚE¨ëg¢ºFÀ×$' z¿ÖF.çW6:u%Úꉦ]Äéié»×°Ç»¯¾¢éÀ?NYÿZȧö±íMÍÖа ^€çf8¬•2ÈiLù»H8O=3äÔÓáÐ\– zÙç]uòI~hé{¶7|Mî8¬kÎç*6_ùÍuÌõgb øS'F05ÀôÖFïèË]ŠD[Wq8k ^ëÐ3“ò RW^®ó;ºê÷L9º såËwk^½E°ôÃxß“Åݲ®+½âmSLu$x¨/©Àº8õåº@Û(HV¡3A‡Р6aÔ¹ Ò§¿ æ8ëݯ&=É%Ô‡²®ûµ†]&ÌT•?×°Π jg9“À¦¨:×’)c—™ ž_¶9Ɔú8Ä!pòf"D`Aêñt(nÖ2ò}j™JSµôý°B +0/âȵŠ1´ŠØ£+ŸœñÅ©#À"Lœ;ûÞuù{ÝÑšp'ê%ݤ¯.0ò¢Ãhвóp àö ¸‡CŒ£˜6X6`žù·^c:b,¢ŠDš9âúXÑiÕAz©BÜ»¢¥Ã(¼ÏÜ-Íš› ¶mSB½†.Òšá†'Új‘ Ûkˆ‚§¦úr ©© ·ªÁö§ù–8 Zžç¸@í0Ë—¡b)Ä…¯¢–%üò ’QY£ô…¶ýš&22ìeE±0ÔSṡ¢-Bê™ÊNÄçe…~켺óÔt EÖcl:Ž\–Z­à¨¥Åµ”î¼Ü‡4½v¾)>[p5K´ýNòñyÁºjnHôÔp͸< ý¬+fØ„Šë×­ M®‡vëÁ•èÌEÙm0\ûË7¼‹#øðoX¯åعñ}Ù3-£[Æç=…Œé81„N=Ï}úZ bžÞÔ$A[a§H&{Ø^ÃŽÔ©ý"èЉ#ô°z ÁÄöìpÉo -8z+¼À™±#cA6¢©;è*ðú*VÝï]†ÃˆÃg8\b á%¤^ì¾pvÀUϯsRÄß2ã‹ûÚqœûÔÓdXÕv¶8Žo´è-Ý.çåÉ!4ñÒ,ñCGJðuù„¤Ó%ûÕÿgFôRŠ—(þ†¤¾z¥ “àâ–`öâv‡Å~Ïfcw— ;…¬´ ž¿@T—žéjïD©ï‰"œ[­®D²ù'ƒ)àô@!åîÅà¨å®D-ýѿܻp›¸_ÆzX½~Ú0ž$¿(t5å½jY£ ãM-ÏTc.7ñT5ö·ó5Á¸—_+œY™ˆ/FÓétš gæSkxMŠÙùöâ4‰8]„¿ÖáÒ| …dø:7Üx!ÿD//qSk8B~+8‚鬿خ(÷Ùuè(f4ù_ :?? n˜±à«[~~<'^ùùQqÁ¤Ì&…¤£!?пßôÿçcKendstream endobj 21 0 obj << /Type /Page /Contents 22 0 R /Resources 20 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 19 0 R >> endobj 20 0 obj << /Font << /F17 6 0 R /F18 12 0 R /F26 18 0 R /F24 15 0 R /F27 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 28 0 obj << /Length 2596 /Filter /FlateDecode >> stream xÚµÛŽÛÖñÝ_! } šÍsã%A›Ø† ´ˆ‘¡-—¢Vl$R%)ÛÛ¯ïÜι¦R×p½€y®3sæ>£—ÛgÏߨl¥T\8§WÛýJç:ÎóD¯²ÂÅü[mw?Eoÿ¾VQ¿Þ¨¨<¯ÙþõÙëí3µJàO­28›qa ·ªNÏpѦùJŶ°vÕ׫}8º³›éá—H€¶+•ÅZ9‹ 8—ÅI¦sBm«Ò.ú PÐ®ŠÆšÙü¬êõÆd.y ×> ÕÆÆ¦ô¬dµÑ¼Gñ{LŒ ”Ýž/#J£cƒ­€×&‰èæ:ª=ç‚Ö±JÓb‘Up<Ÿ·Eœ›"ƒkxº¯«î_Öü»Æ; JàÓ|àÁ¸Ö™§@çH-w{þ›¶îpœE÷%ÊNNËΡæÁω²ý0ò¤íÚÍpf.´Bd‡²G@ÂA~À~-¤é7Ç'@‡±ìÇ+Î=¾{µñ/Ý€¬u,N¾£S"ýÕŒŸ  Ö€æl´‰ ]²³%nÂ07I*Ü|…b³Ñp9#»²¨#ª2Ã|âÍ{Ú¡W!ã›–—ß7ãA¨Ig¬r´—×–ˆHc>Šå²,ÚXœ5CŸàGþõ²\uç¦Þñºã/àð _ùóDüNVǃLN8þ axL—3ËA \nátô }ýž zk|„²Ñ6(_S•Çãã:×*›+€Å¬,83S† AîÊs€Zö‚ë2 2z2ÌÆŽ¿M[/ô(¸V’ÒbÚlëŠY9”ü‘Oj<·W€OLæOãG ߢ¢K^‹Yóª²åAy:¥ÀÉ„H˜r¤>!QrpÇ ‡ª;)œØ_Ú`5M×ñ’vo¼Æ¢zN¹ÿA½_YþÄúßÈ­¸VøíAž:ØàW' Û|°néI´+¬O¬·oVß%ãÐ4Ë%ÊÇO‹opqaÀÝó™²DÕ±c§"¬~ŠÛkân¢W(ôBþ—Eô:6‰É¯æiÁþЀ¥äÑôyä|É^ „@»`/ì×…mMÛ6í\LÓ›N#W@}ªÏ@›Ÿá &E-GF±§HÌ8yKè ÀðžÌ½ný¥šA¨Pæ:lׇ°z*{fC/hÙNñXGV/Á„¸’£[ÎÔÜÒÄi‰‰™ÁÚ+±5„€Z›²×"{ô^K# ^`ÐüÎrní-ù'xÿô…- ¨µ¦ˆÐËñHdam2 +>5›Z¥jUßœÇ'ðzô<)Ylµ—+„0üœîDù@èƒÿ5Ç Õ‰¾m>ÊäÚ;ŸÝ<~;šÌ÷»„Æmw ÖÁà¹Â¼edZã§q0Õq¦ó9,|AQ9,¸Óž‡þ0ä\c__57äѦ¥§>òÂ4,á¥úo­§bô\’ D;²ü½¾¼ÜÈ—ììeÒ­ìÈ÷Mƒ{—¾¾²sÚ¦(b£s_||÷Ý ÓËm'¾2wÑë~I -D†íäñ¥*É Ž*’' ¸ÏŸQ§-û2øH®#íKu9|!Ý®}`?ˆró>2ëNju¼%ËÝYrÎ èØC+C–ŽÇ½úZ)›á+I’Ô  {j0Ø"‹Þ ö´ÕOزÃQ–õp™8.#÷ †ñÒ·<tÒiñ8¾ÐX©šø ¯!@Ƙë£hŒž-Ä)¼ÄŽÀp¯‚{”Ä}Z «=Ô©.®sö„J"Q-ö$pcÁ¶À §xgÏ$q(eÎmýž¯¾þZòx&Øñ?¡åj9·U}'íú£†«WÏåV£Ëâ"O}¦Ûâß/=òã2“D´ æP~&Ù"G·Ô8Æ—Ÿ: É û?ò®¸u°‹/ü‰?Ä îž‡( CyìPPïV=Àútö8)ÀÜCEŸ!¼­èU×VõÇ?”¡¥2—å™u¬¯=¸.¤ø3ْȪñnRôµ–ăO>wCï×Oõx¶ ]üÑçhþå}€g%rít&æ“Â^¤¢™ÈiôÂSÑæÏðßö:¢yŒIþ×Ûzj`O~U‰Ã*­ø¤ŸG§‡éçѹ¸ q’·* Ùµr/Hÿ÷·YLendstream endobj 27 0 obj << /Type /Page /Contents 28 0 R /Resources 26 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 19 0 R >> endobj 26 0 obj << /Font << /F17 6 0 R /F24 15 0 R /F18 12 0 R /F27 25 0 R /F26 18 0 R >> /ProcSet [ /PDF /Text ] >> endobj 31 0 obj << /Length 3119 /Filter /FlateDecode >> stream xÚ­kãDòûüŠH÷%×ÝîvÛ ;´¬n¥EÇ¡£»Ë yœÎÄàØƒí0 ¿þêÕŽñ@àŽq?««ë]ÕóåíÍëwÊ­”Šrkõêv¿Ò™Ž²,Ö+—ÛÈÁ«Û݇õ×ÿÙ¨u·Ùªuñ°ùxûÕÍßooÔ*†jå`m–G¹Éíª<Þà I³•ŠLn̪ó«ý¸t k·ÓÅ_Ùg];ÑÑßÜm¶Ö¬ðå°Ù&Ú­w¾öCÕB T=~Óõ¡hvµßqç‡SèÜ««7:[{ÞP4<Š0º]ÕÝìOM9]Юk¼òëw:â©t”ÄI¾Új%y®Ù¿®ÊЏ ÿ]lchÜàÇwGømñÇÔÿ„7`çà;ø=ÂzßÏùÌ9m¶‹‡¾o6€êÐUM_•€·1t³‡Í†=R]·çDœ]¼YÅYâ€e¾¯`߯x™v¿„”QQ¬ãLV—D\“¬‹ºoù¬»€vªñ3Þ2Ovã}‰• y,šÆwÑfk2$ôa ì~’+2Wá@â·\º¬¾‹•) afxõR©ØXh™ÈËV u„I<Ó…8²Î¦r³¶©Ÿ–î¯]¤§dÕ©Ç •®Þðµ ð½j—SmGéìQ¿xíÄÓ?Gƒ…‚Zõ<dá’óF;‚ÃlVóAðÉFÌC¿\؇E~h97Z 0L”fyàðŽäâŽ#¦ßå0r7ef³³««Ý‡©†çÚYàhóù•i±¥Äfä×òìig5šÞ1È‚Qàív¾õcäÈ76³;è,²ùèÙ¿øbé¢ܹX›‰(ƒñ±‰Z¿«ŽCŸ6™ Ô‚R :c ZÄ(‰Ï’³/Á™–z;ö±Âhð%М›Ï=EÇ@¿C1„V%›Â·à8G4ˆL2ß!¡áïìülJÒ©W¼‰ÝJÎŒ#X@çN°‡ cøgìúÍ86®}œ9-6¦= :úfÑIwÒÂÄvª4‰èIݳ…¤=‡b Q=/ñ¿<ÔUY õ¯xèZZNyÇ+úêW‰=Ò769ÇB|22Ë×ïqMÃ0ØÊðâøPKgßáÆã’/·ŽÚ,.øT%P™àªÏÀu 8¦°†QÒÙ:¤W!Ò—ŽËйXÿ~D¶Í6'7eÏšƒPî?À¯Òð“}äÙ^]Ÿé ¾®ûÅøÁDYb¯ŽâHæ¤úlË.}`dôhË–Ui¤Ó$D#¬,í …I¢Q I#îyôñ(}à.ïÑ’9às/9ûi‚ÈîWŽŽô÷‹F6’ã(dsw'ÐóÄw’ÆN¹l.\r¸æ¸5BºgÃ!r2j_ôÒT:ãߊ¥~F¹sОÁÔmƒÂ·$²¿ÁîÄBÅ¿.ð>uQæt~%ïMåñ()gC@àËú´óÜybùXš²%œaø¥„“€` ˆ++ÈÊBHAÌ¥˜YœžmæQb£$¹0í$ųʫŎKzqÎ÷kBâ¾ç‰A2„>DGÏMqôýCQJ—ÈF N¾¬àO?p<]r—q:"1ï¦e:£ëÉV°+=†Õ&I ÈšÕ¿â˜træ‚„ˆÈ®‹º’Bݾ]5ˆ›\<©Ý´t­!#³µû ~>C`¬Åž"6)Û´=ÿÊ2úí~þvOÅŸï±ßc«Ã~…ŒзÿÏ·e+b†w¶šÇͳC第6 *mµØhÌ" æd‘Z–¯pè+’8•…Á*|_`Ì6ž>¡ø¦,O õˆV»äÆOýhu˜«3*À"$în–ߤa„é_œZ¹éšÎ§NÛi ¿”\‰}âHÎEZY#p&$Ñ„£uJÛõ¿7¹ÅB†KÈhNÏœ2‚}FŠƒö‹® jð!™q×Ù¯,ÊÒ1Óê|Ù¢)mª_¹:ê=G/týšÇ(ÚKFS<óû8ï›ÙúgCMÖœ‰âu§Ä’ÅFšJªJu}1³_`39Yo!ãcœ~A3Ûùž”X¬éggN€Z˜”u%b›@>‘ÆjäÈ:R—žŽ–Að±%‡$> endobj 29 0 obj << /Font << /F17 6 0 R /F18 12 0 R /F26 18 0 R /F30 34 0 R /F24 15 0 R >> /ProcSet [ /PDF /Text ] >> endobj 37 0 obj << /Length 1085 /Filter /FlateDecode >> stream xÚÕXKoÛF¾ûWðE¹Ù™};H€¨Ú…€ÒXJ²è‰JëßY¾LÒK‹Nš±‰&‡3ßÎ|óØ}»¸zy&`N)Œë-2k9FÆ)fè/Z,ßÅ¿þ™@|LRˆ³Cò~ñËÕÏ‹+ˆ8} 2$ksÒ©(ß^ù›RÛ˜tRFÇU´îDS’MûÂo+¶À*†J¹HgÚ8]Ù?•YIVÁvµKÐÆe’ 4ñõkÿ« \óØË$bâ‰Rqvô€_Þ î[DÆ9 ‚åõ¿®e†H@3䄤YŸwyH*¦­…Fê/®xPg\‰VWæÑÞž‚êdíõN¼ éKAJ&4ʼn®˜”ÊVò­7¦ÀJº”Z}m°F“œ}5ò¹²mXÊ{2}XúЮ“TŒwçÄ3À³±hV(x_#ìèº÷‰âñ*-–!cÂ0g¤n„§ýŒçc—“Ø—9ý³ßúÛ¿‚ƒø5ƒŽM³ð«§ñ+Î$ˆÿÅùëïkù†0f'ú:…€ É´†–¼ù]±YNÀ¤¬QÚ5]‡”Ñ¥P•ªESÞø¥ïÊ)­Ž…í+?µñ3´Ši­×T4µ©t»¸Q Xª)Z¦ÁÁCE¤gToÚp áªà¨¡W@Ëb¿ë€ÝïÙq¾ùBüÇÂýD_¿… HÍœVj&-âåF!æÌ]qšâº¢¾Šmu`—I”o²Ói#Ó7SÈÚ×vUÞí=u–“þGð•î°óÅàŸê²BQå­hdÞ!s–XÙPlÐzèÇ®¹e¾ú߆`Qñ7VË!ù/÷¶`kã 4Ÿ™G8œ­(j²E÷!¨ t]C3‘*‚rªf1©k;g{_ÿÞ…ñ*¯ï•~8º÷÷ ÍL!ê`»éècvœŠš1L*ªàÁ)¤856òzV«íúöQÃ Ö `šƒî,oΫ ¶*Êh7rÁqUV³Ÿõ³Ÿ¬™B½Ë<̉¥øÔÚ¯R_^z+Ø'l±ï-œrù3¬ŒÅÎûÄO6eˆ6ÂR² 3äÍ(+Þ´y¶¯Tü TH#¥/+t}€ûç Û^"6RT­zÕŽG~¾÷-GJûÅûI¸Ê…9Âýˆï)j³šåãÁÉŒê¿5Ýÿ!¨ZØóáVÝ!‹ ü¥{Êâ3Ï2ùâë›|w¹;,‹mxÛcý£-äï¿Cì¢Ã^ ö/‚¤–(8*±•â•à]M¥[Án,éu;¿O¨!ð›4âËyOY‹”Ô\Dr0o.î·˜Q}2T AÏ'Ñî¼ý»bÑ1„–†1šý„%˜r²îX7Åí¹9;ñ-è²Ý °(¡Ã2>›¢=< ϳͦfÊé¾:˜)³v÷8:H®˜²„qÎAR_8p$8Ñ×9ò‘äõžEµFÿve:endstream endobj 36 0 obj << /Type /Page /Contents 37 0 R /Resources 35 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 19 0 R >> endobj 35 0 obj << /Font << /F17 6 0 R /F18 12 0 R /F26 18 0 R /F30 34 0 R /F33 40 0 R /F27 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 43 0 obj << /Length 3361 /Filter /FlateDecode >> stream xÚ­kÛÆñûý )Z*>Ñ»Ü]r7IØn 4HZ¾¢œ àQ”ŽˆDÊ$åóݯïöÈö}Þ£^ W² ­Ë¾l÷Uí¯[LïyÓ6{€RO$¤<D ÇÖy°PþDýcà ð¸Á¿“Q'¾m‚×ñ÷€МVër Htµáêýcë÷à©(t Ç)=žaÈãïvÀ%h œèç)Ͻ‘)šÝq_s›¯»`öª‡[eFFp²¹¡”†#࣢ͱ.z¸5î!Í8¹.‹]>¸æI2kðE­@ÌëˆÄ7¼¶iùëO#Ü ºçÜϰÜ5Þô…#‡mÌOÎ’ƒo¸hÖc÷ãÒàâ±(!韲€eÿŸÿùñÇk¯JÙ™…tN¯JçÞê\ñ´‹3ç´_}_ív@ Hî!·Ðñ€ç6Ëý¡÷ö/qhÉùhä6/°÷÷åøý ¡½ZÚ$ºùñÕë˜a‘\#ø lË,{©á2p¤ê‚]‡Úm8ødm õLVr¯‘Œ ¤zÌëà´HÆihBŽ "¾ë7\ï,ã¡âTº oD,ÁM¾Ø{ ²= lxœ{S ócdìx°ã&ÊÅÒë4Nœú/XœÌ|A`áD¬“ì<°Ð©:_t<Œ¡S9u¿:M&¼G£]uG¦;¿¢ã/úCêóçt»Ø»¿kº’›o^¼ð:$²ØÙôL8-˾a™; ¶>dÊ2²±¿yÞî*ì néåÛ$óA&± NH’XJ¥é„ A5R0ð¬ôþüÄœ':yø †Xà$iýš6Ü¢©)áÏ×öÃ$9º2h|;w'«3dßôȰIuŠû>€»O6äf°uryÐ9’Öáê t¸öÈ>ÛgJq‚L}ólqaÐmV4™D{’‡Î:‹«àDð÷È v´rp÷0ç^ºá"¡C …9x°?©ÉÈþh!+\12ÁØm6üõó2ðžGGvŸt–G)âªÃ‘và~÷P}€Œ^,ñ^ybèyã/.5û.V £¿Óú Á°ž¬JÍÍ‘ÉWgqœLþ8yø‰Í=âFéÕëÁ­?1M´¥QÓ‹|Óì»òÓ¬ãÊbB"PäìëI M¸˜àÃÊ ±$X4BÅ*ßñ$[ß|œ ÉB‰ñ—’dG©¯½¼qŽÓðŠÇÖU×Wp¡:ʼn†üÉkqÔ#Ò]³J!Ð5ྦྷ> OÔÎSC P†Ø7ëxfWݶÄ*dq8½.Qúk¿¸Ê$pŸ·Áø×ëyë÷~¬rhß é•Æ)FqJòŒTVÇB«T¬ <ô@Æ™€^aöR3Ž ÉÄ]3ÐWÒaãt6e÷qÉ)2N…þ dòmp n”;6$¥„ÈõB.…J‡”tLú¬â)§Ö%gŠçH¬ ™Ø“u©@šÉø&vtƒ¸¬ð Aïvå I&"^ÕÛÏ0.VŸåN^UGÖ&It4q€Ý™(œNÂݬ ¶h(NÏ2ÚÈØ:l ñ ÜDÆFiëm¾îý]"¤ä”h/ÑÍ‘ÓM±[㛜r©‰Ɖ†-'6ß 89nÌ^‘õ¸çYœÄ©±sZ«œ¢Û`[W#Îã$]iˆ“ðfQ±&–]•cÚxÊp×¶¬Ë–¤ ,å³"º®ÒiŸ†’IºC¢rXO´gîGqÈstÆÑB´R”‡þxJzÁ:PêP<è5”ªIR³†òä0ÑòĺA®úAAØ#Ó _ý †Në’Ë#œÃæ#!áJ•3ö3›Ä6Ñæ¹ã¸v‘€IWé™p\¦@°S ŸÁ=+9Š„µ&z‹·ŒÔY rïc®9L¤&ÐwaÎBƒ÷¾ÒľB±¼ã¬†FŽ7gœåÜùö¦ 2ž–2÷À˜ŽBž˜›Ž’g¢ã¿9øö¹=’P35H³Ñ¶«ÎÌÀœ•³œT&ÖV™Áæq?rÃUø’~@]¯ ôŠ2?Ƭ ‹æPÓ rðAv.»jØÊ$‰ƒ-S¼R°teíÏž?Õ5–N¹ßx¡kœ)5õœ"û”Ì<¾™E.%Iž¦bÑû Ó§qÙ×lñpø;TÈr>}?øzcÛðP‡.sý üýfÄh‚ôÝ’ì ü½%’¿ç#Yù®Ûh½|ÉS#Å­|aÍpÐhFsn‚ËŒa ™hoªŽ¢‹ÁüZ dòÙß#¥t´G—h7ÁÛ±†Ð|çò:%l6`þ Á¸ªëÈSt<ާ£‰ ÃH°TºÄ(÷ËHà}Û/&¡B¶çÛyÀÞºÈOšþ²~JÀXTÂ-`öŒ#%Õv¿Œ”²|†”kÄåºÅ_?ò÷¯>g‘; o á´Í#”XZ$¿!}õ¬0¯IIǶâ©Ä^œîÓ£…²n«hÑjYŒ'ÑÀ‘7EFôTìž³aÒÆ"uÁ†yÉ9ðJ$ØUi²E’ÙØàÃL±¿úpõþ±X_‰ÅWœ(ÄE÷ø– "ßý•ŠS'“Ðß]½»ú÷éYl€¸ƒ¤Ç±ó¸ÑÅ0<}‰qf\ˆgÃy Ûv؋청vè?Žìñ³dÛ|‹ú]T¯´0!]˜ËßÀœjÂÞ<¨È T™Œ³òcÁñs,P0­ìó\_|MäcWÈ*ÞUûŠPðlrCh£ˆSʆóˆOÐb!ý¾F5*bj\ÀÅÚ.>#⃗ œƒËþ§bU€ïJ?5¼‰v:MÇxHTÎEaš{·â æ_!¬æÇ¡Tòó)½BP1Û×cx‚f —aj¨¤shÚI0NÁh*ÇeèÝßå½oq…!çSid>•üÂ…tìž—ˆÇiqœR • Š×‡´öÓÜS•}ZœExuy¹á d¨2†Âäð3„.ßûe2þ­`x(ñ‚0°‹`ŒÊ™áˆÀé¾Ü†›ïNï·clÇ?”nôAC˜+’„ƒW"ß”‹þšêœ ü•‰‰Þõtá·Ý\ùS°ãNS–“wø „íìc‹qš8sþØ"%2V ëβ¶#©pÁïÑái––øÂ'½¼\Ä–Tô㪕À8B0ñÀSyëïí\óϬ8sëKÃØr•ówJK%.}/ƒ4ZÆY*ôT¶ž$JsIº‰­^D ʨRZ‡Ø÷ “Ä>C¶ˆ%à$‰^ÍÂWŠôK`§1$Õ鳉^b9GÕMÏåJGñebÈEqœÞV-:ó¹|^ þ1 G¦‘{ÿË3’¥“=ƒþdÀùÚyE?Bƒ=ÃöŽª;$@ØeEp\ág+çY“Ê™ŸHÁv¿ÓçÉÏ0ø¯VÔSêphËnô;~­:I$çÏP{büëêW•Ù ŸºŒ–‹ Ðå_HQÈ-gÎÅXÇÕs)níŠwßUqä mª¶5)ýî &KUÆ3??“Â@H/ùùÙx1ÅYçnÔ 5p ©Zp˜•†Cÿ[g àendstream endobj 42 0 obj << /Type /Page /Contents 43 0 R /Resources 41 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 19 0 R >> endobj 41 0 obj << /Font << /F17 6 0 R /F30 34 0 R /F18 12 0 R /F26 18 0 R /F24 15 0 R >> /ProcSet [ /PDF /Text ] >> endobj 46 0 obj << /Length 3524 /Filter /FlateDecode >> stream xÚZ[“ä´~Ÿ_ÑUyÀÛF’%_ÂÓî&T –$Cñåik¦ Ývc»™òçsn²ÝOj6l1Ö]GGç|ç¢~ssõù—:ÛhΙÍÍÝÆä&Îse6Yáâ þÛÜT?Fßüp­£îz«£òtýóÍ×W¿¹Òÿô&ƒ±y¶p›Ýñ mšotl k7ßÜC·0v;ü†Èç@¯sÅ&sY¬2“Óö7{½µÖDU}ôM_·Muíʆ ·×[“Gž+íK$õó/M:__;Ãâ9„Kïz8ÙÐÁŸº?÷<å’$›Ç‰Õ&Ì{ú§C½«‡Ã#×û±«RÚúŠIn™s8`ØûGnÜ•ÐÚpIÏ"9`}„\y]P‰‘¢ÍÖèà îÿ u`!ö—…ú‚…À9kAgí÷íù€š4jÚ £d%ð¹Çcý û†eJg¤i<ûêe˜ä ?wçf7€ºq ™ßÊïe‡ ÁÚÐâ7‰:?œ»f6Äk$yÈ–Jü W°0_ákç¢òpö—[ûý»w¯D8.p+ÜrEš‰x,ë‰Jqš8üP"HО*»dÊ©ì{áhIWó×ø:¡@$¾p“Š|ì–é máÖ¨ZÖÆ8-?Ú¸è=ÜVšD¿úÝЯ) L5&ÖiÊ4½¿ýÕ_;£çSqžæVX¢L‹æ2c»©½=xA‡‡zسúºÁ ¹r[öžKµžF‰BP¸&HëdÀ¾l¸Ô62‡Q#™P£ó»å°å ªi;Žžq¯çi?)§ÚnZbÌ·áœ÷uü˽îH}àÏã*ƒ²8Èá o‡}GPxœHMôü$Qï=D-¢ÊP§áœáfO0Sˆ|ÁvœrðX©¸‚Š‚ƒzdÜ‘ è”|ÒøáÀ8#åÚ€#çà [ðBÌÉYÚNDWt þCÉ…æ¬*H¼ËlþB½q*vF'2€ ®H„\±nma|¡T0} «ÿé—„!kÌÆElS˜ ®ÁïW?þ¬6ø__)8Zî6è\ĺ(Ìæx•Äi6™ë‡«_ýsò3Æ·ó%ÉÛ¸¤Ï€7 ’ÄN[#«æG«Ø&Iºq—“õ€OõØàåQ€‘xÅ / j¨Ð<†U¯#8+ØŠRº'¦¦QWÛ k¥xsCîN]Ýûž/_@\šéK=¨Qÿ´…„Û6t [P&U Zꆿ%ö3K+ÍÞq;À£8A´ÆchòV¶6QdFf‹Lf„È Å£ö-©UÅ £Ä#"€1¢ÊÙÔ‰­ëòltœ¥Ê¾P ·ãø ÖÉ%a¨?åoõ€ì%ví)%Ô‚‘G, V!˜3êGª-R͇'5‹I{tò>ØóçÍO9ZHªˆœÜDñšý¸´öňÀµ)ä“öߤC£ovôYµ/…ŽÍžØØ|èóø<øÄ7¯¯oÞ½~ÃõñλV¥#¡säÞK¶C'YlòT? NT aµò$×]qÇNœ '¹žkÙ I4¡q_{ÂÈŽÃðѬ"~jeÐ2x£RV:ˆök\6E’•¾<8-Œ ±v/”W,C‡2„6§Â°L±.I]lMºÀŒÑ0`¹¨ ¢Vwe:‹E?C^©|PwîE|¡‹Œí,fžq ¸Òҽ셋ž‡öÈÄïÊÃA<ò?¾Da%ÀѾ@ìŒ7VÌ 6SþXç§Ë\Ëó™8QIAQ³5Vþ×­-°e¦ç+sÚEoÑ2`p‚9ñWþ|˜ÔjNôàðïp:!õ˜/V=ËU 8ô«"M–º—‹ˆ²£“;Ýnb wðûv©‘ýT€Åm®qÊÆä!âyKpx xv…¢$‰]ªÜÒòâ¦cr+èÍ’4$ü)àÎuþêj~,õFe¯,’›DiA!×ÏÄ6.@aTÏ7šªßQˆëÎWÁ²bcpàï G÷Œý£ŒP[P£Úî7–>@ˆŽ RøÈì²påígŸ±a=âçÃPSX](¹Í~ŠÑ†lÀóI¾÷#oÉV£B&râP'³Ä!T.@‡Îä¿Ã·¥ü'fA¹Úñ·nZRt®HWJö|G.¾¤“Ë •_1õK¥£/›~10ôJN³rªº°ª‡àY5e_%ˆ´jÅåW‚vHb¸d§?":²EHBõC;e¾x+âV³ýö{l{wÿ?¾Ù¹4ί%7y‘Šîñ^ò,úG‹,#½ôüdîBB¦ùk‰x4[Dða݃ØÝK60O)ø“—"äC¡mÆ=Iôªuï –×J}M‘ç‹ Sqð‚±#V$ÚñD"Ìe¿¦ý4yÌ “ä#ܪ À#`YNþ@;„ •$›ƒò˜Ï[ðìÔµSj¬#H =W Ýfq–¸pÌãΣ;]µK "Â"1BìD›]^±0{0Ñôäƒ÷aÃø\Ã]“_‚½¶`,¶Í$=únP|èF'µëâ¾:衦¨z-Ñå±…Ê &?¦ò¤ÔkBaA(\ð&9“õÈFˆX’%:úŠ¢ ‰A*ßq ÏV1xÐÒ¸çH ‚E )Q‡¼°Ó9°‡<¼Ýˆi«:…£è1™ü¯IYÞß÷ϼÄjkÂe²!ìÞqzGÅÐÖcØ×pÜG‘±È:ÈiœÛb!~eUÉðeêb¨­ûI*Îs¨Úþ ¦Ì³zWÄà¤\;m»²Cb1»‡#^õ‡Õ°<ÎÙÓv{<ÕÁ÷CÝøÕ')ô¨ã"Ãü>M题=NÙ‰šiF’ÆYj&½ä±e¦ÈV1¾ê¯d‚Àv.MÆå__ÎeQV²|î5'u£\êÙ0ìC†¦Ÿ¿‚²y0Œ/h¦Ðèèt[Ò Ÿú·ù“G6‡Éž’°ŒïK‡ƒ¯VuÊetXó—c“X¥I.~ÖZ}jKñ­%ý?žÚR€û®'K3YÁŒ…)‚„ ¿ºc©”qüâNEô5 fÏ΃´Ahß¡S$Ïlçd"òñ6Leßk¹rûd!yòJ^Ùä,L ¯×!M›¤jJëBó˜¥BÃA¼ð><ªÙ/Ö€œ(U¤u™pý©ÊçT°Ë‘s‘Sà^1e;ð}+Õ ñ{.",Òt> endobj 44 0 obj << /Font << /F17 6 0 R /F18 12 0 R /F26 18 0 R /F30 34 0 R /F24 15 0 R >> /ProcSet [ /PDF /Text ] >> endobj 50 0 obj << /Length 2498 /Filter /FlateDecode >> stream xڥ˒Û6òî¯PÕ^¨Øbà#9];[ÙZï%SåÃfËE“Ј¶Dªøðxöë·_ H 'ã$v 4šîF?¡·w¯~¼UéF©0·Voîöé0Ë"½Is¦ðosWý'xÿa«‚n»SAqÞþ÷þ~÷Jm"ø¯6)àfy˜›ÜnÊÓ+š$Û¨ÐäÆl:·ÙO¨;ÀÝÍ‘ß":™3™0Žâ|“Ú4ŒRÑþ§o°ÿM‡Lðxüa»³ÊU “=>OÃusÏß"•ðn›_È âDÆ5 ›Ä•û7Ï Ë¦íˆ]vR?£R@•Ù\’Ò,ÊN›ÐD™%QþÝð‘Ûîâ8† æ.Ž5Lzp­\ÇÓß"eŽŽwXêJÅQ˜štKJB| áqXc'6aƒ>y«Ó`ìeëOÛLeûº)cå*^Úã©·|üÌeÝÏVƦj\nX9„–Ç‚Îj¨éäË–ß§âËVg~·‚¾…Ý‘iPZbC“Ú F 5cÙzç„]HX* ­Í—(w¤¾< Î]}¢íqnƒóØI¾¶Œ}Ûñ«§opÒ²õ(DBßód8t(âx`ìÚÃ[žÇc‹ß>0¸çí\‰×HèXÿô ‹Li¨w!‚¯ÈÔ¹‚Ž!ñÆ‘Àé ²‡vÙGöCKŽq/Hížßïo¶™ îþuóVð#­#]Äi@ªºº$~€žƒÆÝÈÎ^w}ýéø(ä›ÎïÜå0vlÓ 2t^b-à #/ZN¢íj (/€‡z80 çIp_EŸ¦ñxæ7«¥7ORËW1,˜Ö®)‡´JC×GºŠziF6MÄ9®Ãݵ+Ù(TFyì}Wœ@T~ö…7uG6ØP[-x¯Ù€ b“p|ˆuª<‡˜¾™$Šc­ÁÏB O¥mpƒZ weKbmÁ¾nc Lü dV© hÜ8ÑÁgWÒ7ýëp Z‡*IØÀ~AÕDê³s<$ã†w¯l Õ6vdj&{9ŸùD`¢{bŽiòWÁµ7B€UD±l²ÚA>!§‚ðîGX|‡d^oñÖZÔšà3i¥Eà@QD|ïÍšÍ=úC·;åAY48È :†ü(©ÊíÚ2öàŽÇ5+R6 ­†8ÿV¤B8a#Øž¸lÚ÷œRŒ©¢iÉ'Fô†C°P÷-:¾„mäÝ}Ãs; ™‰£ ÞsØÑQ&6¾ ü‹+’³£2a/õ fÿYÄÐÛyøõɈ¾Àx—dz ªrЩ’\ÿf•_È`Y–§/Û“Üx;ð¾ ~,Û’Mh<[(fÔd“] “«v±õ€]œÖ¸Õ êÛ(õÜ^W˜k|›ô¥õÌ~YM®s;¶šͺ*f$¥6GÑ$ Þ½~̓ECÔO°$†ã\²3,~BnKüè †vUZmCøûƒÂ¦i¼~HW,ð8gxlœ¿ ¯¯èûñä„[_ï®OÌ"ÒñRWOƒh-ØÌC(1&6°LÔYƧ‚0&÷ÀC30¤ýôÙ! EY\A2εñÙ5½²/Æ2;í t²wÓúš+nˆÇõRó}ìXæ‘òu;hÙ¨Š]Ô¯¶9ÔQ…Ä,˜ô‡à Ù^œ@žWWqYËÓyÔ•ô¡„—\AñŒY$2Q„ôu% /änîÜó´àu4ÞŒìâR«ÒBÛ1ÞT,î¡è * ¡œÒ‰ Μ«É©¿ ?ˆb!I<7B†+¼KêgÁK¨Ñ©f…0]K¡y)Z½Cb+Eã¢ïyåŽÎ物-dí±)N59â">!¶HœÒG%Üúb±ä ”Ï’‡­õ8\ÀÜpzÜ‘ždC&žÌœÕ3ìvž­¶¹ª£'q/­ÌLN0nW9ìD/ÂþÒúQýi-îì ìX«|Š1³ÌðÃ,m} är†Ç?òûñ1ZßÇË&ÒÇ[Iui©;R¨á7ŒÁ­?J.­yðý½ïãu*’¯+Åg.ü@ç_Ñz˜Y’Gú&N¸þ®`}ìE5Ü@… ‹åEB~ºm¸¦ö•®Z¥vÛa¥à>{ž×IÅr Òþ¹» è]R´rdWF›œ…J{Xmœ«¼O¶÷/O$F¶WEáÔ¾!†ø‹™JâgüÀ»µì²(æ1KE‘\ |‰á}—¼»mdçóqº0ÏF–}ë]fr—®=ºþ'öb¼Î‚4ºÐ›Â(žåÄÅŠÓÄ)T™—›¶¹uY9ª Ò¨OôruLqOkÞLê­Jq +z¤õÂå£Ò™RJ¥ø>§K ‚ä?Ž/8ÂâTõð•GdC“Ù«òˆMççKˆ–½(Š‚D”Sê_uj¼màÐu˜ÒàK‡K·g¬jì踧\i¥ Ä…,f¦B¿éÝ¥Ú¬.ûÒ-àx’¤©3R¢|ù¿b5‹®G”#érf¾Ø€^};A»UÒ)‰Ä0œIŒWY®ï‹{¡ í5ç+Ô—¶T!Q2¤BÕÙ|·C1ø‘G*ÛÙå )‡á3g_ñ¡&—žrU©I‹rå'IˆîHLÉKÄ~I£³÷ËP J4 µû«ô ^•‡ à®{Õ¯/zl”gOÜ*NåÂ$Ífn…3jàMÊËf>…ÀB>Šg{Sò~E8¿ç%CšA쎎£ó®”‡*SW®DL†¥£ÂÃh»§…O5¯j·-ÎÀÝä€r¿wñ‰ÂDédý$™ïÙ2‡™Æé“ó€üMça _‚¢¥âÝ­ÀŠc äàx©à•o# Õ.¡ª+ð×é.|S„öB³Eè84:K—ÐRûzöW™ÅÓX±Ðc²Ô£y9O¨<^×ã"篛t¦➦ ˆ«äú*âˆÂ;¬Tî¢E_í¢2§`”‹‰Ô!‚ËZ&‡ý‡¿òÒª& ô-P‡ý¹ôΑB™\C·zcAÉÙü%CÔ¡Nó©9{úÛæ8›8ßóÛØ™~»ú 'ŠC(&ì&W¡2‘¢M3¿éÿd…îendstream endobj 49 0 obj << /Type /Page /Contents 50 0 R /Resources 48 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 47 0 R >> endobj 48 0 obj << /Font << /F17 6 0 R /F26 18 0 R /F18 12 0 R /F24 15 0 R /F30 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 53 0 obj << /Length 2935 /Filter /FlateDecode >> stream xÚ­kÛ6òûþ -p2²VD‘Ô# $¹ pEsEÑú¡Wd‰¶Õ³-Glö~ýÍ‹²åj/š,b‘Ôp8œ÷ŒÞÞß<¯Ò…Ranm¼¸ß,â,³,ŠinÃþ-î«ß‚¿.UÐ.W*(NËß︹»¿Q‹þÔ"Ø,s“ÛEy¸ÁE“d šÜ˜Eë›t°«Kà·D@vI¼µ6_¤6 £4Îèøû[®t–§å*Nƒ¦>.ã,èy­Ò6<,÷ͪl >!”Cª[\wÕyÃz¹²6øÃ•}Ç‹µ<{xÙàÐ}½y䕇®¯ˆ @Üòbåp oŽŒdÓ0»p\6D3A!x¿+zŠÿ0ÀÐÅJ¥tï•2¡1–ï½sßCHA”Cçxào Ã~W·÷µà¤Ù»gÏp`‘i—õtÁ»r_t“mÿŠl´iZvŸ ¸´ƒ5.WÐ1ÿ®{ìzwàqÅ@ÿó÷:º”¢Î£0N HïqlzšŠ:ŽÂ(×V€Nmƒ¤ª+çï%¬1* u’Ú)sºâ€€©ê•uŸëu½‡ëÕ=Þõ‘ß°ÐñP°='—4(à{šfJˆ8|†oP]Ú‚¸>C¶I©ÜïhP• ©Ò-Ëõˆ*Ôò©¤ViŒT]DT£æà‘õz/—):I;÷qpÇR^6!hj³qfZi¡èÚX¯é·Q˜äÖÓ_û}'|66Ìbx>çJ³2:µK(ë~ÿÈó²uZ‹Ã)œu¬xýPñ–[ÇSбZâh[£ÎM6€dêVp^nÛÕ0e¡aܳi›>¼Yf*¸ÿñÍ[ºD4U’ ét!ÌÙÙ<%¤ÁÅ´|'“#bH¬:#"ˆ5ëýŽm³ö6ovîÈ£G|× .uа›ÓnÀÇ¡J’| 3þ)6aÅÞbÊ¥ø€„: ­1™€Šwƒš|„\Ÿ±K£ÀZûõf ~(èÖmÀ;é <É%äÁ»çì×aØ=ÖȆÜ_‰° ÃÈ´cÍ ®‰ŠÃ.rN€#Ö¾Y£|ö¼òi ÅfZ€G)ØÜ÷ˆÅ;cîOG §‰ ÉÇIŠ. žb.8œ6(P5'/¢>á³!? =O«š¬¯ôd£¯!p!Ÿbóö4 PÄr8Õ{´ |;Æ\ÔQ•ï—YL·ÆÞn$'Þâê©õg†‚W»–·sŽöÍEÐá(õjÕ!ÁÍ€í¬f%a®T"зl"ÞÀ£,ÄüÚºŸ _ 5ÀaIçu® aúĦL°9‘ Qú üb/—dIl‘$4RĻ奒^“À0”mq³! ^žÍ7 ce ‘¡àøHƒ_ѾehÓ@‡û½Ž£ÅìÝS›„qfÄ£Ë7†]0»¡¤k“¶ ÇK²jöîYféèõúyú¬ùu„—âÁÁ§d»eyt•’AFÉ–WÖ>5åB§“u¿ã¾¡XšfD¿äè|mt9YÜ]K¿ã½dî>¶¥Þó 2\¯*'’×Ä'Ÿ•zÕÁa-Û w—e­³Á&Ð"ó(Xä7)!}œó…¤ ˜¡µîÀi,É¥’ìï(Ùà“&NѺ¶üڟdzõ˜¿B˜«ä„aï?˜G¼¼óyå˜@zŸ¦3sv!ˆ­>V’7¼BQDqP}¶ÄÿŒiªI¸Ä ›\˜ƒ*Eî °Þ9Qe¡hÒ‚½ñoX0àèeÐ÷@>GѦÈ÷„O@÷õº-|V6ÞrºuNò½K@OŸ+©TL^Þ3eNbc€€ì¢h”«1ŒO},”AJç±X… &†bŽþý“#/û~§ó«Z9¶:Œ 86è¶Ó\c üñæ·ß£E…ó7Pçä™]<`ª=ÜhÈÖUìçû›_n~>Ôáê#UÕÓ;Ä6 S ûG8bÞ @ÏÉ18•‡Ù¼$F|”*¼k¹Âþ_Ûì[ðÈ$*L•ÕߎI#Æ/qÉ$64Qb§\Ú‰G…tIŸ`“ÅÕûΗXÂjñTR\ePhê«Ô»Ø~ÕüXôT6%â?°’Ø S_ó㌠á.4×ç5X¥ Â™ýÒO*¥A…!…¶ ó¿,ãêåŒtÀ‡„œŒº¤Â”äüŽk•û¸¶ßرŸé˜os³Â¨«]ëÝ INÛ<„ªøJräd tõXgœøÒ¹%É×ÿý¼É€pëG’tºvƒ¸W–«ô\¹\YdV)ó•ÂŒgƒ|ªhDÑ E!ùÆQûÈÔR?†›O5u¯L†wÅXé%[¢âìJ¥¨§pW*Š#,Î!¾èY©©®Ž9 x¦17u¼k ô'.p 9Œ@’øqüÄ®r|]÷çP@؈¹/@ó¢Å—…/ßä¼¶ðÙˆñØŽ8[íUÜûc褦•¤Û‚‰~MAk© U>!æìFÇ>óáŠsŒ1I±ÁÐÕôvËÓ'ûŠ'p»ÜøÛÁü§Ÿ¾¢þ9‚!/Ó>qÚbjgç¬ÇRâ㌊GZ¿JpI’ÄX00fÇüSðŠ ¼5—[aq3&Ó²"Ε±=}ÐÇÁûÉÁ p7ÝôËý< NÝP’³›ç2”V¤TpN7”xÜŽWé’§IaÖ5í$§Å®ˆ”gÒ.ݱb¥D¼-V/æŒ8šlßsáõ]Í}óPñQ¸üŠïN?¯çnóýü"mî©Wሖ”|hžÕ ø}qòγ}…6xÆš¢œÔ‚Tö¯QouwâYàçå_:”ÊÒ†~ øßw|Å;îÐó8:ÿvÎá,¨>u*%,¡&òÊž°*xuãõíÿ É–ÒyIC‘5wg—úšiC†D \üøyÀ!ý¼œ­&¥ñv)÷R©ðÀíî1kÇ>;·L¹Ÿ"ŸAG“ Oë ?éóIJÿúr¹Š=/bÜHµøós‹„·×òaÀMj M¨|€H*¾ø)£¨¸$!`+SbÆ/‰²eMº›ËžØï‹c ê 7ÎÇŠ~ n.’iÂó¾CÁ-£÷>ijóášä¹s>vÃ[G(¬bf꺌Rzt6ØZÁ.“±å‰Õ?' äØ:»R,SÑu’Ë5‘ èk”ÚÇg\¼jj¶¦+ æEŠãŠÛ÷ÔÂÆ^bÓ¹Ib‘\þj ¬Â8*ê Ê¡;LÕGHŽ¥¤0#±Ôž™qR¬.6ºLôJY‚øNÁÂFOœÊC›FžÝ«™ÅÜ—4¨ÑŒQc«JY²0Tw›pkä$d'}´Æl£igŪ³ b÷cUpΔ:Ùƒœðì­±­H«÷éC N rrE4˜vÔN“†rÆØ’›(„­¼ ãs!m/œ`~²w/f>E«È†6îͧèKà™OÑPÁ…Q …F哉–ûCÿ§øendstream endobj 52 0 obj << /Type /Page /Contents 53 0 R /Resources 51 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 47 0 R >> endobj 51 0 obj << /Font << /F17 6 0 R /F18 12 0 R /F30 34 0 R /F26 18 0 R /F24 15 0 R /F33 40 0 R >> /ProcSet [ /PDF /Text ] >> endobj 56 0 obj << /Length 1549 /Filter /FlateDecode >> stream xÚ­XëoÛ6ÿî¿BÀ†V"V”H=:¬h2tØŠõC1ýƒbщZ[²õH ûßwÇ#eIQÚ¤k‹Ò|ïŽ÷ü©g«Å‹ßxìpÎR)gµq‚$`IâNœJÃg•Ÿ»ï>,¹[/=îfûåÅêíâÍjÁþr'Ú$e©H¥³Þ-pSD‰Ã™H…pjålzRh½!ñ*DCŒ™‰ýzéI.Ü× 4¸Á¡l0¾ u £^³Ñy,Ì0˜N×O8Â÷‚ö^°$ådM‡Š¬QxCU’ðsÔ¤ºüãíüB?ÊhÃá£/}øÇaþó˜w¤y*8ÃûçCj.˜’Ìó¼¹²Æ{ÔMéá':<Œx•êÖÜ9Zð= ÒªÔp"0©&ó=Ìê7÷šõö²†¥‘Ñ`øtBçÏ'¾~>5—YÆò‹ñ‘£´x*Ü1tŒH÷»‡ˆ7çÇb$G›¶Æ­;2´ ›‘Ù‡7±5YßtøRXha[ZëX)h˜™HZJC2ÌL3 Aà!ã)ÃêZå8‡Á¢(L@)$R;à¸GwslCÉ‚(ä†x§Úëjé±›/½0ŽÜZµ]]6¸ˆÝlNZ*˜<5 .Ñ4ÕvNªåCE#B¶0IÝË®5´ã:E*²/˜–¿)cé³X„†8'õ•Q¹D}Zš†E¸·ö1àC M\$±jŒßÆyÈ¢8Nñ¸”q 6„7K)ݬ.´Œ-êùªÅÏx(£qÀœÎJP¸x„ð„I?µ–­UÓmñÉA䮳’&ôRE‹&[‚‰n–´Ãµ¯aµE³Á™½V”HÙª+ŒÒú„1–®«îêúİ«è÷iÑÜÛ­9-vûíÍsCÙ^gÈäåÜ«=ÁOb>Šô/µ¡w_aÄÿ($=¥ )Ûdß´–HxgÊ€© :ßçšÐ7•›¢¤X'‘CÐVÞ«7Gãéò£lÛaƒ1m@(Cg:ˆÖ>õÙª$ ý¾NìñM÷À —!ó¥H0O¡@”rXœ_øNÐæíÂgašHçqÊœÝR4å]o-Þ!OÏѲœ>\FPE"~­‹ç±±ÏO M­Ñ›J¥òó R¤¢_]>Ñâf3D§‰>°PwÛN髉kÐBm×w@L+JDÚ*r»änñÑçB; &–Y™a–ƒ&ÛiÓ` qƒTö ‹D]£¨@qž°4ŒÂqˆÕj£jU®Mzgø¨«ngôhLZ›ôÞgÙ©ºÖf¼²eƒŠ ûë]¦“§*Ù\Àøª˜VÕþotÓÑW=ý®(ã©p¹Uí‘Rø“Ö}FÞÇ"sµáGâpƒŠü+ìîÌ10Õ‘€u¢°—ž×Vu„rUwi¡Œ¡h­ŠšæŸ¹²š20j¹¤}1ò^¡>ZåAµa|P­áÙ,ôµì죿®ZkäÁwË’xì{SÄ;¹ƒbÿ?›ƒìßTÌvéà[ã¾KÏ ¤iäágÇ…uo…÷Û=] ‡ëÛäps¡}bKøñC»ïN— wWžžÐFÑÒ/¤> »~ÁÝÏ=ÀF£ÊFO-¹2»ÅiÜ,UÕ5[Ãaß5×ö*ÕËZWUÚ•І-½HDîïT†4 zÄ8B[¥6åÐ@(;)àoásýî[¡ÿð½dzendstream endobj 55 0 obj << /Type /Page /Contents 56 0 R /Resources 54 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 47 0 R >> endobj 54 0 obj << /Font << /F17 6 0 R /F26 18 0 R /F18 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 59 0 obj << /Length 1972 /Filter /FlateDecode >> stream xÚ­YoÔFø}…%úà¥Ù©ÇÛc QA ¨ˆÒFj%ˆcO²F>v}dUýïýŽñ® ŠÔ1žã›ï¾f_]®~x-cGJ‘„¡ï\Þ8¾ö…ÖžïÄI(bøç\æÜ·¬¥Û®7ÒMwë«Ë7«‹Ë•t<ø“N °:‰JB'«V¸©"íH¡¥œÖ87GÐ Àn¦À¯?š2€èÂXx±¯‰ôOëM(•û“îp¨û=Œ?ì`º-ŒŸ&GÆŠol6XL‡åéãPrcãk¡Éš¹nC_ÀÐÔL|‡ÛÝöŒæ‡!>z¡‡Ì7×0|>cÐ"‡…#„œ“‰ˆÌw|~×,\˜Ò œht0 ‹ÓÖ{44<å«û‘6)íéi‘Ûƒ Èf9ÞéOluÏ“Š‰Y–J(ê)ËÏÏ’ñÌcß½iZ†BŽQ´qÁŸùã=Ÿí¾°Äíî÷pñûâl¨(.ê}sÎ^ÃÖR¼°ŽcµÖ@.®&¢æÇ¤€ÿŸCÚ–ÏT°ŸI¸G}_F÷Ý/â¯fà%1}ÛO)rÒ€t¯?ù¦Ëuñh—A¥TW_:°õ›/NaúÙmk¿)Ô*¢4üJD‘ ³P`òña~è^àânø®ÁY3@Ä‘»Ì`p‚ :½åem òöå:Qîå//_áZ¹ïÞ1ROó /d±¹~ïSL}AèBå7ŠÓoq#D´ZŽha‹ˆ!Q»­)MÚ>ñá–çi_¢ Îæ÷q›PDn7ìv)± aB¡M€)X˜tÀSi6=©JKD"Ò»¶Ù,¹Ã-âK«Š¤Q>øD¿2÷ï(¨;ö=÷Wܵ‚gC™âµò¯øn†¦®àS†V=c¤ÐÆÉ¡-ú#C‹Ø¬TD QvŒ±°_rkÃF ¼©Q‚Èqžâ‘Û´Æ\è!Ó & ´¥ŸXà¬L;K »ïzS‘f6Ê“ÂWa0×Ða[d( 7 HeÙàÎÍ—[ÃgCgZž!ã Ÿæ$ÚãÉBæ¦Ã]k‡¬o¬ìtu‹$úµÖÞÉÒ²49#M‡•^¥ˆøÃzLŒÝó9ùäÌÀÐö[Ô]ŸÖ™Yr„‚È+ä¬oA< >€–Éyûš½Ârhx“µÇsôík6f–…–yÒ²ìà ¦5À‚¥Ö7öˆ¦9p9ꆘ¥MP °ÄþÅ;·äuvÑ VaÍe-k¬ka`‰¥¼ûyð<Œ"?I BÐf·¨ð1p{ɹ3sf½lÖ1É(ÔÚºÙÃVé¡SªDh©c Eú¿@[ß3Ç’iwGöÖ[NÌ[—Æ)§#R(ƒu sHu©]C©„íÊywÖ~m| ùòAù9 rÜÅH …òŽa™"—ZS¢‚OÖØ¼*)jŠØ¥ü@Põ¢Ve cøH­†t­~`¡¡¿Ú@öûl²ÞfhSE{’˜•"TR:Pl­è‚\´¦H 8H‹d±×kí»#ÿ毴ڕàI&.­‘R†v\5ø˜¤õèzìcX¿ÉÈÝT)` Ðl¨ÁD3k¤e?:â¨ÓQú‘[ '•ÍÜ%°#Å# ør£O[ÏF{ÞÂi ´ƒEh= !Edmaƒ=ç½¢ž!@&sW4CÇ«Žpe}AÑ$–ü Ël,‚$¦mÔ“bìªË!gQ©ñÛŸÚ’óGtZ³Ö¬Çê¶ÃÆ)77¼…`Ÿ?ƒñÙŽ¼ìlÆ5µYÇžϱ  2NúÆçÿ‰hKÏ øÓDFÛèNú²³¯tÓ2TAŒUjb/£ä‚.òb‚ãüì+ „ÚC¹Éj.N/­sæ âMôñ~0ìGÕLŸLöE7i@÷Ø‘Šã»í~¶--½²2ì[S4PG^w3ãeN§O*ÚuÎm"”¾¼ ™ ÌŽÆæä[Êä'xýÍd ‡KP¤º|IÁ•ᶈæ_Rš ü•×ë~¤~†ñjöî0'+ïLJ?fÇç׃_d %¡‡†Çþ~õáÊsò•ç¼Yyò:tøsIâ;Õ ª"Lc9ßWïç¿LÑÑo±A^± •h(BQ€¯ˆDxq0ËìÚIDA꡼®¢DÁûBDàñu¹¥F(ŒÝt]Ô,uW=¦Op‰*+õFÔ–°MþrÏ S§üìÁ{9°#ú*˜0 c`:’¶Xm~þ͇×Àø ™r U fc Év¶gã ‹ ed8L-5ÀBÚÞü›ˆœäz8 º€ä'†ço/þäCBÝTö×\‡Ô!ßÃ&™r·$ŽÊ¢%†Ê¨”„пBGYd= @¹ãAa×»2¥6¶¨ókxážw¥æ\7-†[ûê›”@ª€¬÷€ÚV=¶7'…ú±'â$L¾ÚUÌüD éÑLiéVé(ŠU×.¥(º.-Ó‡‚Þ†ð.ëÇN Ç* "£Hõ¹²×$‚ÿày@‹[æÔ:Á”±´ÝÒÔ“¡oñ ¹Ö}¢uBÓÃÖ"Lõ£Ý˜ïAÿçAÌ*д„ÇÎ!ùà_ælémendstream endobj 58 0 obj << /Type /Page /Contents 59 0 R /Resources 57 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 47 0 R >> endobj 57 0 obj << /Font << /F17 6 0 R /F26 18 0 R /F24 15 0 R /F18 12 0 R /F30 34 0 R /F31 62 0 R /F7 65 0 R /F8 68 0 R /F43 71 0 R >> /ProcSet [ /PDF /Text ] >> endobj 74 0 obj << /Length 1582 /Filter /FlateDecode >> stream xÚ­X[o›H~÷¯@Ên…“0e€a†v·R¥R«æ¡ª¥>¤QåœPp N­ö¿ï¹ brѪ­4†sûÎùæÌ³ÉëR;RŠD©À™-ÀÂ?pt¢„†Î,=wϾO¥»™zÒ¯§³Ï“ÓÙD:>ü—ŽY“ˆ$J”³(&¸ÅÆ‘"J¢ÈÙdÎr'ê¬×þ€q?é‘H;ZiáëÀPSOÉÈ=½…8²†æë§4òËþù›ÊìÎê€È­Õa›ÑðÃW>LàG¾EDŸ'#EŠÞTðöò ¢€ánÝpvø“.ëz2¡&Cä3mF˜Dr:—v¹Àrª’í¦Ú*COm|7 ™uq¢ì ‡ãE}¼0vaw°SèÙ 3è­X£Ì=;óŸÃÁê9U©gQµÕÄ ½w=h0|í ‰ ‹D5ºß«ìo‚xŽé1?4²­‘-ë—ÕìV¹E•<íëÿÄvøºböÈ;$¼t9My«ôª{ncEŽTÛKâV'a=H–ùgl@¤ÒVDúA²«…÷ãéCFCb‰€60Ô̓-• ̵ Ÿ1W#Ò Ýí´G"d]Øã:èöß±wÏ•£×öËaóÊ[ÔXo-—¹:¯º‡¶4ê7kVàb‘6Ë*4O²9y”ÍñSl^ãr}ÝRöx?¶æИÂð3ë2U$o¿y÷Su¸N?1‡]bZµÒæ¯hi=NÀg¹¾¬l“·™ÙΤõßVÿ²Îíê(åûaì\Eq(mO£âcŠÚZœ)לc=¨én=\¬lƒ»ÎHØf,êgl,aß§ ¥{s™—Wc´Q¾|\Tx˜dâ~G;0°¥2£>=ž½Ÿéξ¼ÿ€Ïʽž—銱I<`FV³q'– ¸•æÄ\´\ÐÀÞz¡¸—ðN³MåÖÛ.1Gù[$P•Ûýk¡ã8–­Î›í3˜W%SXlè3ZÄÇ‚<¯š|mA„2`D!Âh*MEî/JÑ¢©[ †÷ Û°²’®òvCÑã&«×$qå—+«³¬˜`8O9º‘Ûâ=ìƒÀáPkY^‘mÜ“×'Ôýù‰øÇá¢%`¡€'“¸Ÿ–,pO)ÜòC™!Ïp†«xú¸+ªMÖ‰Ajx¹*í*&/pgèð PÉÍ!̹9€ÒÁÄè%ÕÌ1¯~âž²i¶ ‚–ÃØ/éý¶&sO¢ŸM¶”‹¶©U[êIMf5l…r»jÚ‚ŠB,·½nÞöÀ’sîšÙ¦ÈÒœúžÝ²!|®ŠDû·^Á‡hì'ahwl0¶G#¡Ã t¼žœù –`/V~Œ¶7“ó ßIákøóćÁ(ç?…L’À)&Òh˜jÙ®¬&ß&_‡ßÉ}sô¬b‡# B2J@óƒá)vzÁqA?§Ð£8‰/14e’ú85‘Kõ7;.Á,/—Ô ±1à%14±Ë¿½Ê.ÛÉnëK±fhN×Ú^)Íh) c5µªŒFàSäûÄ'ƒì`2I”i»> endobj 72 0 obj << /Font << /F17 6 0 R /F26 18 0 R /F18 12 0 R /F24 15 0 R /F31 62 0 R /F7 65 0 R /F8 68 0 R /F45 77 0 R >> /ProcSet [ /PDF /Text ] >> endobj 80 0 obj << /Length 2591 /Filter /FlateDecode >> stream xÚµYmoÛFþ®_!´w…Xîò½Á}pÜH:w±ƒ+Ëš¤,^HJ%©ØFÿüÍÛR¤L)pMqßwvæ™™g×oo¯/u´ÔZ%A`–7›¥‰Šc×,£$Pü[ÞäŸ_ÿ½ÒN»Zk'ݯ¾Üü²xw³ÐKþëecãD%~,³z~/µòß_¶År3 ]ÃØõxð[ÀøK)£Àå‚H¹‘‰iëvÕ&p.Wžq>|\%žsóñüjµö"ß¹-›¼Ñš»Å‚ÃÄãø˵ •‰}^ê}³ÜÈ);üÆÎ~µ6‘³ƒù­+o«‚Gô;þºBÖ(I»ZÅ!¬êÎjçT ¬M"£íÚ(;—.W ÆXãã*6ötо94Y_«ÿq·ß¢¸‡»­È¹hÓú ”CþõÝovªö+:Êr­͆]k_ù~ÀºAøÆuº¾¬*(êÄIùs ¾†•/^½â^ ÄÑjµŽ4ÚÆÄh›AzE¶AÃP-#õ ©xŸ[Ò}!›²%Ьĥ‹œ[LçÙxNR¬ ÇŠõ¢H…€•5{I:¼ÁŸsø¹šµE Њ팯¨ùâñ~%8hsÖ‘oü€›Õu‘—G-W ]Ú³lvmÁ )¬ý¸Ö¤uñF:v-Ї´ÞWÅOs‡ÓFy®—„A7H„Wë@ûNN(¸…D,¶t¨ÔXœpÓ%´€Q4Ú„ÔÁSÓçÖðƒ€"ï鹫9›Y];Ÿ›/Üþ•3Þb"­+óâ‰êAà WÝŽUü¬³d|¦5¶ßây×ÖS¥Ñ~E²ýÊll—Aر]<±Ë9Ì b‹mXºa¼’H¡o&û@ïý–j ×D21¦óC[gÝ»åD]#€Ñ`çWŠ[I [‰Ï7äÅó¹§d繚·k¿J­ì·\Êvõ¾¬8@µß¦=—ö-ÅÉ­‚[7&[S°O{ ”B+ÌH"Lñ·ÉªCΊ¦»ÆG¯]I qõ »À%=¯R’Wã™ÜÙÓ ç#œúQPâ“aOÆaaL? }tÒÀK`ñ,Š® nWbfcúA^rz+‰]ßVƒÒêPÉÉÒFŽk ¶¶EÀY݄͑èn5—žõÅÓÏyC¸EåˆÂ#Rf7æP’Bž‡Ì¶ ]ö1‹ýÁ$RH[IùÀmÇ’ò¡ŽWÈ)?sMxB¦xå†X=æYh>×ÑØ=¥¸õ`zÆ#‰]áÒ±/çÃÒCб†cÆ S\aÛÖø+&C¤ƒÞÇ<õO^fðÜn³“à]Gè .÷”c÷6Û½è ÷¨§üwÃ6¡¨ÐÎk£90P¼‹8„õÝ£ÛAùú ³N÷r^¥ŠÏ×PYãnH³oDÛÑ>,–MY2[y"—èÀÅËq€Ü͆%NofœÞìƒß ˜g‡Ã~ææ«ÝD¹¡k¯ 5ÞÓæàN\ÈŒ.kË}?ÝÉ&#`ÄFÙDǨ¾¥{Í7‚Ak/¬ÜBhóTû'·=PH4{­bÈÊ"ÙúgX—°~I¦:}eÒ>ÜÂ0Zz¡Q:r=|>ú}ñù‹»Ìîò—¸A;Þã”ÒIb–õÂSa¢­W‹ëÅ¿ŽoQÊëñ’ü"5ÔUDÉqkøïÔÿ¼žÕ9†Ýádà†ëœ“gbY×H,ϼ¸£`ƒ5p«Ž Ù.3{i—p4…øÆ¹˜Žð[<ôÀmÈ/£H¹®LyhrHlÙb,†*/p>uÙ:Iq’ùˆžþÞ¢¸l¾rœCá/Åñ”§CýÿÄÍhÉqcÇ¡ÀŸ®@ÌŸßa*½ÆG5z¡y§çpUБÄ‘çÅÎù^²E0žé°/WÄU |4&×ÉÕáKÁ¿€¡!žŽ"]³´“i˜  ‘0³´‘]'Êhp„IdCd¸éZj#dì Ú) Ú_bHÈC<Î<ø•Ûy'o¶ØDd¾”„¨á™Ð©CFI`Ÿcñ©fñr²¼ƒÙ²¢-‰ÎØ&¡§ »¤±®o–?’°Á ‘\i[ệLlŠ{‘ô„­`Xo àò>º³Ý¬'qÌô”Ò{Þ3oÊ`Óœhmʃ¦û¢©C¼Àz ô"Gn2S‰K2-7«­eK\7·/$8ñøâ|ª“ÄÊøžM]̺FÄ9={¾[ÙüE9 Ìô2à\^V)Ót/‘1•öÍtÅä¯|gŰq…ƾ„[U(ÓglË¥~ßÌÝé;ñ•5ºêôEm œ%hušSJ‡8<ô»š¯°YZÙ'ï™G+Æc70?|BÜÉi ÷a§gv¼üJÍü-P» b0Ç÷ü-p<˜2è‰ó»ø¼- —ó§öì¦ÿ…I endstream endobj 79 0 obj << /Type /Page /Contents 80 0 R /Resources 78 0 R /MediaBox [0 0 595.2756 841.8898] /Parent 81 0 R >> endobj 78 0 obj << /Font << /F17 6 0 R /F24 15 0 R /F18 12 0 R /F26 18 0 R /F27 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 84 0 obj << /Length 788 /Filter /FlateDecode >> stream xÚ¥UÛjÛ@}÷Wè¥X2õV»ÖJÚæ-4–J1´ÐôA±%[T#ÉMò÷3»Š/¸Ðörvv.gfV×ËÉ»[™xR £µò–…§R%Ò4T^b´Hèç-×?ü»oô»`.ýlü\~šÜ,'Ò é/½„dS#Ld´·ª'£8õ¤ˆLy]î/¢s’ _Ãy2Jê@ND˜¨”M'dU*í&Ú ›’†f7ÈùôØùЛ«X¨4²WoƒTù-¹½ˆS×µ÷¡ŒènUÒmƲfm+„Ö*õ*ñóŽÄ²Mn‡¼èÊ[Ú%Æ/‹–=fã÷-ÉÖùPÖ¹Cö}^@ß¾r÷[7³Ö ürÈÖ™hîkŒÁÜzÀmau®28^9 ÃÛ f‰(Ò6æ F U¿ÎÖn5l;¸¹ßlm'97±2ZªK¹>'9"†&vÒ"˜ëÅÂÿXXQŸ“‰ GÑú™™¢áé’Þ…¡¦Â³ÂL/{îBh2{›}Sœ lò&|m‘»›ïvÄW9BBㄨ“þ6oìé#§Ü®¹ ¤arçÒp“œ‘¼Zå=¤‹;fv´¤lŠY¨³¡lYÃÐêîm…t¶0üØ¿¿DTb. 4Ù SÍvßÙ2òoÒTäÙÁ^[”Bú.”Æÿ÷Ä4ÍÓÙÂÌfYÙºfS’’´¸•©T¤F&Ç®|ÝÛ±îÛú ‚š©èín‹ƒ¦…Àpª1>Öø¡” ×7šsÕ: +®îü`“;˜íRšˆf¤²¯Gf^Å û¿ãÔ3ÈŸ«Sæ?uV@6³iÀ¥ dj!Ð4> endobj 82 0 obj << /Font << /F17 6 0 R /F24 15 0 R /F18 12 0 R /F26 18 0 R >> /ProcSet [ /PDF /Text ] >> endobj 76 0 obj << /Length1 913 /Length2 3475 /Length3 532 /Length 4111 /Filter /FlateDecode >> stream xÚí’gXSÛ¶†¥cèM„°¨ÒCˆ‘Þ„ ½H3&+J‚!4éM@PPAé¤*XŽ  H©Jéˆ åF÷ÙåîóóÞ_ç9k®óã›c~ÏSTÐÄ\FC¸êð$˜,LÐBZÀ䘬œœ&DTT‹¢H8^E•!è‚WÈò¯¬¨¤ S‚ˆZO"ÎÙ…ˆkIüÁ ˆC£ðEr=È5Ð(wÀœ€Æ$Y@ÃÝ0ûy 0½@¢ˆ‘…À`‡&W@gýéÉ%ðßÃoÏ?R> Ñ‹l ÿeS ›ÄðîþÄB Æòm ÙËÿ‡­×õvw7Fyü,ÿ«Sÿ–GyàÜýÿ¥ xxz“@"€$`@"þŸRkðwsHƒóöøgÖ€„rÇ¡5ðÎî S•Sø=ŽóÒÅù í`Qî^à¯8ˆÇüÓ ¹¿|@õt5ÌM¬¤þ5Ú_IO²ð÷¹¿Ô¿ö“›DÄùvrä.ÃÈBòúcçðËtðh‡wä•‘ˆò‡™€Ãc@?ô#;†Êâ $ò€Ü™ K B~ΕÌSe(r-:öÆ=¦oñŒ žn|f€ò[ÌXùæA·rhÓ£ÄàÍ9­÷t–î —cŸ{œúì²D*àØ|ô=BH2ê^æÒ¶qú;ù«ðò¹õÂÑF±éò¬M³&Õ×>‚Ì¿IÎðÇœŸˆ1îdIòáÓc®"n¨Ó$9–Í„®RI žZQ2¡BŒmÆ‹nr$EÞOw\¸#ØØc-×rïîjÑççžê¬¼8{ß´ùá\å|ë’G·ÛRUZ¹ÚÝ-„üyÙW¢œ›éŽhX_/CócÔøðÅýäËå6Ño³‡ï½s„žÏ:WEô[‰¨*¼S •C‰OÞŸz£]ô ¤©Xåo^,Ïd¯]5«³äèÁ:bÉ©H;Æ~æH›MtºóH«‡jt;nió†´¤¤c#þ¼ùÐ"ÿ­,ÞåqºÖ@C¹žügeLÛT»ÎûX„ëÄZ¾j¦»>rYºˆÒ âÂX-(ëkv/Ó.QT:rT‹JóÔçã›5ÓNÿHšlWÈÊ0U1iää¹.¥òâõl­oˆë§VÑ=OÅÉC”²¥:/6dÖNÝÔMXè#Q;UcÔ•Œ¯Ê¼L¢²äèˆd¡qˆn\°Ê;7@䆊vFÏ[¿Sà×ws]Kã§,Ó§ŸØÖf=Ób ã1:”!V#ïC窱Õ&eUïÕe8 MB³Õ)2²Wg+šnq»,ñŠÈ ^5£m@îð}›‹¼âþarÕ¦ô·ô)Á‰q•#§!æ ‡ùy›ÙM”Ï;VÉûÚj‹+>•¢s8©×¶=ñÁŒúAlÏŸ§òé úÞJZs“>6y­Ç¬"‹šs6/.AãÅÉß„»«W{±åzåpƸ’Ë}i¥w\äh%Š‚rŽX•wäl§‚®µiÇwL3ЬîoÕ³Qæ>7uöÁ_˜”Ê’c“6N–”0ùžd8ó!ˆuûYºú£ª±‡Ufÿ¦gœYÏ1äóÔc?é¡´Zž‘[“Â¥põ·}‘_Æ{ªV.û.2 oäõÇêY1´š¡x’,—oy‹ŸÆã¤2¡½‰‘5­úÑ`ðX3w³qŒ¸¾£Àöré"gRÇ©g©Õ7¦€„“÷|â”Fè{’ /­—ñ¥Æc½‡$:OZúšvõ8—åÖ¢ÄïÎ(¹¹ _âfZµàÏ)´/4õÁÓóÛ´$NI1ì@ì[å¹ÀOÑ5ê¬~? U‘;¥.ü¢Žx¦R´¿›`?túI(pGQ°ûw&ç«(/dp® Â0Ÿ¾O}w ²wüÜ;–¤¹çXí%ÖÇ> ¿Ø\²!=¶ù¸#&¹¯Sñ±-ìà*ÓÞ®p̰å¶ÑØ÷î³GGÃ,ÁÀÔ]oÞݱI÷Ù¯C=)Ö+caüMÜ‘=¾ãº·lDŽN#a͖蜓%Í¯Ç ®˜‰®Ñ¤6bÔ¥|V踟¾•2˜ÊõJ@aÒé° AšØMyÖé¼ìr1{ý%¿"Òz[{ˆ)Áuä¸3gÇm2ÞªÝ[¬ÇZ°9•}'ÿ”JÅdOqà,(ØtÁÑÞªi4ƒ–ö‹}žP\üeõhEVÉk Á¶ñ_îêªâ*ì€ÃE$ë$¿&÷¬ÇGôîLxåñºñzyÃ<ýgª2C¬káwûñöùåV|ÑÞ5“'í3ÒàqÒÏ4/bëÚôf×½™nOƒÆtOMógìú- 3O‚KÂÖöSW'ŽØSß~08žv;0Û€+GàôùpÕBˆ(÷‘WE>É}ñûèj [ÜW»übù&Ik{8O’vãJÄü‡tÛ!ý®[(Ÿ: iv£õÝc}í_¾„§Yž^K­CwK¦¨®Ö¨Ç­0²× ܬðÂÔ=¢4u'ʆUnÄ8^T]Ž¢ûH[_özY0‰í|‡/So¤~ì™uš‚¹Ã0" ØSõÖ*õÙÆ!&ZäÍØI÷®9×Ââ‹§ÓßÙŽ¶ß¡Ð*¤në†Ûæ:^Øû ÿyS¥"=«aánFÜ\Óé1ä{Lí9‹£¢šn ¾çÄlÕ ÷÷+ž°e^±|à}ŽÖ0Â#òõŠ@`é:ÒëÓy¡…V¥ö4ÑL1ƒ«Ó*çi”e$üó SiÓFejÌ·]ês·ù!t›*GˆB)Õ$U]JÜÛš1¼ìuvEÖ:ëì¨Q¥¢ÊíYh´|½z=ÍáØ¾ºÈè®^ã Ÿªª­傆;¾T‘—âÅl×&Ô»ä%?5Ö÷[sjñ|Þb÷ÞÒ¨Ù:ñ[g‚=³þª¡åÖÀy¬qëͬiKÜë¶D&q•ý.–f˜,­äsbG}LK=¡ª¾3ÇÙƒÝÒâô–O4ÅwhŸ%ã°`Jk.ÓtNØòƒoÌÅs@óX’Ri|׋ïÜ+„eqä €ª:1p>-чchZw:&®¾UfƒÎÎÁŽó†¢6´éRx—ð7Dsbô÷SNˆè'@¤ÕQB£Ó7˜t æÌººY†æ« -V””ÔÛ¥±ËöŒ)¥ Y×(VÏoÎκ“¢Øè ùáªe0ë/<Ôܱý67Ž¢ΜíàøAáÕûí-]4,iCàÂå—¬^ ç 4¦»<‘} ó–ya‡ÄeµuŽ•SùZw7òê ÌàälAÁŽkÃzwã&&×T~!ön¨§è‹F¥Ì¥ÚlÞa{_³Õß§B±ßÆý…8HÂ’zöIþAÁÍ;m-³v©F/iÒ†{WN Oä:[Ww¿oåþªÀ'¯éM•³@ê=¯w“…;"pæáö ýÐ'ѤTètDÏ•…%—Ðs›DºY]l¥Ç èú“8B”EÓËìÅCš1Pé0b‹k‘C ÇöúÄè”[sCbK@#@?Y2çÚ~¹H”+­U¯Hp߯­¾hI’ë=méîé¦X§#Ý…•DøÃª‡—‰¼Leáa~ ~Vm¡Tv4½EþÐä…l˜‡[¨¿ðKÙ+âö|„ã—œj§{äénAoRßF£'zQnNg¨¨e†ÙQ_ »;Õ;‘׫eÇO^tá$üG–)ÞaÐ+ƒVîia§pvýÚŽ 6DÖ8wÞÊyU˜…ºY«?¡-n!äRá8R~u6;ˆf/‹ã·´ånð¾U5*.KŸ´ÑÖ¡“ÚBO¦ÚsÀã@uã)K ‹1:ïæÁ;Â8Ötà©Å¼aa!UXB™ç%ž\èÊ`vú ô)ÿžûŽu…=ßò0.*z!´sí£Çuž¡TO-x + {·ó»ûXÖ•¿]FR3÷Œ´µÓl2=Ñ뙩}EѼœ,Ó­îà‹Vݪ»\ÊÞÕòˆS«ªÓr‘ôÙoª¿˜6»ŸÉ8!q™i‘ÍZÎ5¬¼™ùý²€SUœ’Öä[±Üÿñƒü·ÀD´;ˆ"’(¢äá{8Ûendstream endobj 77 0 obj << /Type /Font /Subtype /Type1 /Encoding 85 0 R /FirstChar 11 /LastChar 118 /Widths 86 0 R /BaseFont /GFASPV+CMTI10 /FontDescriptor 75 0 R >> endobj 75 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /GFASPV+CMTI10 /ItalicAngle -14.04 /StemV 68 /XHeight 431 /FontBBox [-163 -250 1146 969] /Flags 4 /CharSet (/ff/plus/C/E/M/c/e/i/o/r/t/v) /FontFile 76 0 R >> endobj 86 0 obj [613 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 767 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 716 0 678 0 0 0 0 0 0 0 897 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 460 0 460 0 0 0 307 0 0 0 0 0 511 0 0 422 0 332 0 460 ] endobj 85 0 obj << /Type /Encoding /Differences [ 0 /.notdef 11/ff 12/.notdef 43/plus 44/.notdef 67/C 68/.notdef 69/E 70/.notdef 77/M 78/.notdef 99/c 100/.notdef 101/e 102/.notdef 105/i 106/.notdef 111/o 112/.notdef 114/r 115/.notdef 116/t 117/.notdef 118/v 119/.notdef] >> endobj 70 0 obj << /Length1 838 /Length2 2162 /Length3 532 /Length 2759 /Filter /FlateDecode >> stream xÚíRy<”ûæÄIcIZ…ñ£œ™c?d-É.%•fy13ÌŒ1#$B$[){)²%뱯¥ˆd+Ê–%[¶”déN:uïíüyï_÷sß÷ýã}žïóýþžÏóýÉHYX+è©xȈJa(`  ojcƒA ÖƒÉÈèÓ ƒD¥àÀ¨«+]7PT´†²"çƒÉ}ª›Frrf„¾ìW‘*Ðu…h$ŽLq gÈ•3ƒ€#k*1ØH K&«¯t`Ñ!""a ’ €‡œHê«'cŠ#¨~£‰nßKLˆF瘈u›²€c’H¥Ù€9ÂPfTÎiÇËÃÖÏÃ<Èd3œë×ñëIý­Žs%‘Ù)¨®n ˆL©DˆFùYz úfÎ"’<\®3pdA—âD†úE¢‘XÑ‚Ä 8ÍZ§! ñgœäÖ ,ÍN˜Y”ÿk©ëE ‰Â°a»ý˜úU½Ž1ÿÄœxh$°GsòÅp„œ÷ûß©Ÿ3¤¨DÅ (bUŽFñaœëÃAXpH"Ä‹c…¤PœÀÉÄ8Ri°¯UÆ”3ÛÍ¢|å¿QjåѨ?, žÿ‚Uê[vßN‹Á¤ªPæ?š"@Y­£¿§¤§GeSP ŠJX ª„jh´Ï¿É4Da¬ß@NÒß±#‰³bAXw• yÑåFQP¦¯áÖ,^9n=§âH³üêö þ€—QÜä»&îr}yÇ?gÇoå•ô\£‡–{[6Í\pŒí\ež÷*;>oÊq“^ ˜Ü\VÔ±0…å6oëkʼf—ú0iöÑdŠÂÀæíÆ×R\5öÌ‚š„‹*ªÇâÉGƒó~S’²Žuϼ¤Üë)|-š§÷Y€¯K0ߟò¯æ¨å"ŸïðݺºæÀµDøõ²¿¢^òËâg.¿Ç+ˆªõž4pZê ;µpåß­BÉàî×ÄÝ¿ÜQJé.[ì©j´.ý£†ÍÕ±òf^®YômÃÄÆVuú±w³­x&5 ‹ï™ Ÿ¥oÈ 8ˆVL7\ØyM'Áü$p"õƾŒ‚-^_$LZà…ÂE;¯·V’ü‹A“Ö@íþ{½†Wç j̦„Nx®ßýIœ»\ïØšH®ÒBÕDß—-Ïnl3íšr»]_3ü‘2)3Œ•Y†ï¨öE<Å&}”Ô;ë£;á"p±—°Ï:&mCÖ8ßàcµ›Ï夯Hqìäó{3¯D¦Ý÷Üä´©RpKVÛat7e{𠶬)Ü6pïJM 0£æz1”Ic•‹ªº)wÿÎ' 5®3_ZÙÃnÚrn_™¹ûÍfe-"¨„Ë·Îò¬<埬ítuœuÍÛ«fˆnš˜ÕŸÈPØG©î–;_ªañ¾BöYN£vå¹Mª˜s÷E4.çB>Îu·0"QÇTZ²³.§Uß“ANW„HfÏŒ‘âaCï B›¤¥“·ã•âžüþ¶K?ÜÓãµ _³¥ãp§öûc#­…+ü‡vaEéWá+íBÛ—JÑæluä@y­æSˆÀs×HÁÙ5À(¯O¤ýDd¤h½oÅÁ Þªü>ƒJÍó—Ê–Ù†£ÊžYÎ5“l³Ö}ðœOÁ]j3î«Jp»n²;=ï“C+Ôrà1iÒ¦w¬ûƒµ†7ÙýÏ–}ŽÚ„ÔÀGƒío³äÇã½ôLþXîE°ËÒûýŠš#lU"?! »ËüW‰Š)dŽóN_sçRºýµÈ&Rc®M³CÈjÈsë‡‚ÄøÚNciµ TE“ÜÜRÇïBiõÓ;wÅíÆ“ÄÔFO ÔÏÇíå+OàJ/¿K¨W qzâY€.Òm^³¸{TÉð~oÝYQ¢·wäxW“ ÇfÌʳµVGµÜ ›Âµ£lÎÜÔ~¹_£ U"}"lÙÃMËI:b ØÖÍ mÉžÏçç.-šóáÏ\í6ãen7©qÛ)D ØÏP£lo€ó÷mîÁ^dýjÎècÝ4á\n&Ð}âÎ÷.nª9™)Ǭ/¶¶—öß¼'šqÎŒï~­Ý©ð©BÒkwïLK ²Þa9Ù£QPX1aù9²çé€[-Úƒ)Þ¬³(âz`$›ÑöF©|ÀϨrxt$MN4V_òj±EªE¾eHKLšé¨ê—$òð#ï3õ/Â'ü sˆ.\e®†æ®«z¯üú¬ðÿ)>&“d^n KžÆ4Šn5ÈýL=ä-Û#|)±­ä[”gXZ|’ǺYzÒYp7‰ÿf¬·±YŠWè$ËÂëoÛSåáñ×íæn?‚x tÍbIéå ³28¥û\ fC⹪kò_œ=>ù÷¯™®Ø}`„ù‰"éºKµ‡ô¦çø«».÷Ñ—ŸBŒû„>Î ´7Iƒ«¶`µï7js‰Ä>îÏùPÒ+§‚ίÖì(M§ßU!‘´×ÙÒµ-Xs—o–zß”{{à­Ø‘ÝÅ>úÖ/ð¨ÑEŽðö^úØy³ j•ÈÓ%Ÿ²…\M³1=)à·Írj|ó˜ÏyexjØ‚´m’Gxu:}’¿`~:bϧ“y‚’0’Ë=¤£9'dªOÑTÌ ^é<½(/ÖuaGŸuQzÿæè¹ñ®ün-±Âá=QƒøØxíÇ#r»§”Ëúàaø¦ÝýZàý³3·µz—§®äeëуx2ä ÔÉòØù7*焌\{©?˲¨'rUm[BÔîuH›n¼ù`òãåbGµÃ£g/>¢M7°åß<Š|ª¥oÍz|¡Á¿5±·5óÒúÁ>Í1˜òCôƒR龸.xdrÎ4¥e„!ë¼jﻥ!掙vëÏ}R j–m›'cüW™Ñ}ŸZ–/€¼¹ÄC §—l{øíÓoIhíò·)Ž/>ÚeØA]=ʽ3a¬Åû¡ä–ÏsãL.`æØ˜RP¨Q4NŽßr'`0×8¢tYw©a0¡édHÏ£®ØJïªÕþÆ`¡>²_QïÌlbç)×Ü üieº3ªkmš^‚ÛMÄ'R*©DøVî3i¡¿ÌÅTÆÎöËúÝU?xCùG …³ŽÚû)]k‹zäu¸ýž®]iYìǰGû®¦(„+Eo¼‚ª8®¥Ž™ÖÔ9–x™ƒi+Ø"|H!""±.»s&p°ÔgñµkE»ÞñŒÕ×'“’§5;~‘ ½GdÍÆ@_FÅæ¼²N{Ÿ8Š»Í&¿ tô×B^¿¢˜Ý´AÍ}GôVç`æšKóƒr`ßN”uÐÅÜ~·E§KEôñ‹¹= sQçP/,áþ£ær§^J2ŠŸ^7ÌþT ºø`’mßÿÅvô‰ÔÁ®ÃÚKNjÚù•Ayº ¸*í<<\"}ÇÆÁ*X;ùb™a¶;þÙª„6WKaW¡RXñåi…M›“±eÃ+×çç·¾ái§©ÃÓÆL}*q]Vµ3F—Ù`6g6L°ÿøŸ@ C8ƒêŠ£…ý¦­²„endstream endobj 71 0 obj << /Type /Font /Subtype /Type1 /Encoding 87 0 R /FirstChar 45 /LastChar 82 /Widths 88 0 R /BaseFont /QNZNQG+CMTT10 /FontDescriptor 69 0 R >> endobj 69 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /QNZNQG+CMTT10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-4 -235 731 800] /Flags 4 /CharSet (/hyphen/zero/two/eight/D/O/R) /FontFile 70 0 R >> endobj 88 0 obj [525 0 0 525 0 525 0 0 0 0 0 525 0 0 0 0 0 0 0 0 0 0 0 525 0 0 0 0 0 0 0 0 0 0 525 0 0 525 ] endobj 87 0 obj << /Type /Encoding /Differences [ 0 /.notdef 45/hyphen 46/.notdef 48/zero 49/.notdef 50/two 51/.notdef 56/eight 57/.notdef 68/D 69/.notdef 79/O 80/.notdef 82/R 83/.notdef] >> endobj 67 0 obj << /Length1 1245 /Length2 7527 /Length3 532 /Length 8300 /Filter /FlateDecode >> stream xÚí”UT\Û¶®!xáA î®!¸»»S.…wwAƒkp Ü‚ .Á=¸Ûa­}÷Jî>÷>vjV«6¿ÞûèýŸÿ³¨È”T™„ÍìMÀövÎLlÌl|@Qy6V 3+«€ŠJ 6v¶´·3vóÙ@ v ØäùæùËÇÅÉÇÅ ŠÚ;x@-!Î@ZQº¿Šx€Â¶`¨¥©±PÞØÙlûÜÃÔØ¨joj vö` ÛØUþZáT;¡®`3fÐÌÒÔh†XÚXþ’$mgnäùWØÌÅáß)W0ÔéYöo™tÀg‘föv6@3°9€EÁþyøYËÿYÿÙ\ÂÅÆFÁØö¯öõßÒÆ¶–6ÿ§ÀÞÖÁÅ ÊÛ›¡vÿYª þ—6y°™¥‹íf¥m,M…í 6` ë¿B–N–î`3%KgS  ¹±øï8ØÎì?E<;÷·I QQmE†íéß9%cK;g5‡ºþUü7³ýægw –î@]Ög{Ùž Ÿ¯ßéÿÇ,q;S{3K;‹h …{žOÏ3q=Ù€–vf`w ØýY0 ³½óóà³'Þ@s{(௠ec²˜[þû99,¦ö¶¶Æ¿#Ü@‡çM³7û'ÄÍdþMÏ"¿ dÿ‡xX,¿‰È"ý›ž×Éý& ‹üozî¢øñ>¯SýMÏÕ~/Eëz>a,¿¥ƒžs&¿é¹§é?ÄÆú,Íìd²€ÿÀ¿lùŸ@þÀg à³–àóX›?ðy®ío|>,vàó\û?ðy®Ãø<ú>rúŸtþŸÞå|–áú>ËpûìÏs=þÆÿ~tEDìÝ=™Ø¹Ø€Ï?¬Y‚¸AÞÿW¥©  ¶sþûŸáù ø7›[>¿/`°;Ø07moÊd•ÒRâ#ž÷½VÒ§PÛ1Ù†8kSøMÖ‘~¹Fë¶, c a‹ÔížØ)¢ÕKyDâÈß1îãÇ-W£­´÷MÄZ§iò›äWû˜- Sç\°ŠËC%IÚù½™Ç}û9J´bjÛH‹d0º®uéAÜÍÓX=Ä‘U`«±CAƒÑÕu«¥Ž>òs뻪ožïù‹AÃw¶jº5­=Yø)fHe™Iê6SÇÈ”Gšé0 ‹|•A¨‚}´Pî~ç%ÄoÜ•±¦Ä¢ýÐaJ~2FÙØhÇœ"¹´¤C˜Ä‚;°æùO,ÉÊàǃ<Ø/ؘy>lúŸ âJ+¯èºÀ³ç²>äÕ»èðÖo§Ð—uR f¥Þ_f:~Y8OVjÞË8iòjïþ 3œID€ÕàöÞ¥(Ô^ÕÄõÄH!:Ñn¯ßt{†ÕʼnŠ£ýlÅûµ³5bvvÏ4;׫ ÆdQµ…Ó ®~Xΰ÷çÚšê±vXŠÒ89Ðm6k±6íDQv³[Mœ)JÖK‚ê¨ÊÍS¯Æ öädÄ„ÚmKaR—ØM¸>虚yDžZ ¼gxUnãÞ°i\…”ò•¡ÿ{ªË¥4ñ®öø%—Ä;GH–Н¢¸½›,ýõãÙl?Kdê#¦S³Xí^!Ž$I^Έ»À»:R™ÑM Kº•œ˜ùÚ,ÆUˆu9âZù(fr²ÊX{i5¥× …Ôƒöñ”†p²Óê"+’­žÍÓ’­ÊøÐµCïË bëëúwÌñ;‹YóKxºÀôÅïcߦ¼±½(ë: ª²ÿCèW{p·?ØX Eâã\]Ž}"£+0+ ö%¡àðrÙ¦3Ó9T©Íö‰Æs&|àDžݶ>"™É_v:¼þ›HÃÅ=àC‰L<»ä¾¹'­È´Ž¡¼SàT#œòåÆ:ãt¥<ÃÈ mÁ&´ð‡#V„¶e¸†ZÀµàvA<…ƒ‡X–Ž~ŠÛ{1Äñ@jCr@»c„ƒÌe“&&w­‡ÉŠSQ]SºTÃáÝ„«H–li<žT¨W?Sô£¨ÖsðɈ–FÖùzÜ.ìƒý¥J± Âa‡P`Ì[‘ßA°cKÀ…ûú«fQꢑȨ,±H”RµAU¦Y?:TôÞ¬ÆúfCš¬©kìÝBa~£¶äŠ9L;-…œ`»·‹=¢âzËVèHÖìà%Z‘Ú¶-BZ™ ´?ôÉßω½]½Ü'œ ÁY6¾…rÎLÇû>œtº_çUl7¾ßš‡ò”Ô®Kz„¤IGScÔŸ‰APs݆§Ýoê‡SË::BV^èNa—,qjîY¢ò,H‡(Gß6*z âq_×ʲc‡61›J¯‹3{ŒìçmìÑx˜½¡®—(ºÓ/_Í vs{(H<MòÄÈà„Úø%W[0YS|^ÇÚ’]ÿޤãžlá ÷Eò‡vÒÛ;áy¥yÞ†í:·¢“{§ºTÄ¥…÷BY|yÈÜ•ŠÕàGäÜËùÁµ4½õ»v—¥ î¼tŠvŽ¢ÃqÍŒ…(¿Ãr7o Ò4íy¬9lŽ”š÷j)åØU‹+Ëñf-†ýäkƒ×Ēሙ÷œ’b—ãiõp¢"h9ĸbv‹?! ~ƒìÌLyãáêÞBýàVÖ›¢… åÿEûMEî3ÌLšyw¡&âèUK’G„e€,¡‹ÁL‘ïb»¼ýHõ}i:¥O»' mÿÀkptUMeŽ˜üé|oUÒô±Bë6Ãè÷‰ ÍÑj^ŒÓ=Ž~A†©ëQ“lbÝìÄ©±Nœ càJØàä),LؤàúýËK²ÈâpWÌ(˜aA?žçîãÒ‡utŽíS3_¬Hºã¦2*p?±Æç^¡ŒàÕà›Ó§*Ýaó‡¾i­cèýI¾AB~T'f "gX³ˆskÜè9}¼~ëkúðá”`SQ Ƹ¯(áu'0“ýüE×#9ZkÚ±Ê#D(6„ë1^,kè'ƒ½±‡;ê×(ó±ó^àr©QJ]ÒÏ=!ŸJQ¸n¨arN Ób2ü^}Ê•CVÏæß鵯‹áÝ«~¯ÔôA~¿ü»½BÌõŠˆ¨zE¶{®ÊÆ »¢þÍ[âÙ]snKΣW˜epŒ·œÖ7f{ÌÖ€Ìk眸õ_~Ý›‰¼¨iV›¹Öh¹ðŒ°§¾1©Z{<}r¢lx&žÃb2ivè <â?ßhÈwjA!E¤„O1RÛ]h]è«<Èuá ºÕöûéY"®ä×Ýõø[† ße÷Sô)‰Ø^Áx 4ÌIJ+;"öÇïÝc¦ƒ$ïñ”tin÷ÈÍš~Õ•>`õššÐ<á-åJ¾þLõ€42yO:wPHàD]t8;’+|Œ ±ÊoXs=’¥ÎA²'^êðh”¬-Ð51t€è§Ó”S9ÐM!vBcEذ¦ÅâÈ RŸ/V­g™à¶2Õ¨,*üȸ$ £xˆa†¯uˆI³þÎAÓƒ QÖí{¬ù¹6ptüã4aY{çA\0gëE1ǧêR"KGHÌ77ƒÍÙì²âN˜h‡ÂT㥣—ÅÚ[ö]¹'-®õ𰥡¶e]§Ü“¼æe»|<ì^™Ö^9M¥hî«Z ŒFöøþF fh·GÆ'æ^„Í«¸ú>ñ JÿÉÂ=%Rìæ2¶W­_Q"f€}Ñò´âW?Úà‡#æ×olÀíº´1/íàM[Øø·ß«³¿ûùÕ‹pPÜ#’îœ\!Ê,TÙ C´NÞEŸ¯ hSó݉á:0ÎRû›vóñK­Gé°Ëqú/;¸B‚pö<"c„Œ‡Óo¿d×L†àåPö¯Æ¼]œ#éâ ЯŠê—K',vtƒ¤o!Á<íĈ½ÍcB t</µj»ÇóÙã nnèG™7ùY̘ ^ •² ubôº¤sKgœ~ý~rÝN~-5Ò,Ã%º…¥Cb-+Kú…P ; O3>ºùû}ÛwcÉ ïŽ”=šÏ#‘²“«üŽhŠ¡û–%:"ÖŒnkOcj=¸oòi‡$À•;o,>ƒ>ÆÑï¯HŽŽ„º‚ƒÍ_±øL½‘šëæ‚ £dlŠB.Ç30¥šmv2ÛºÚþ(Ù%’J*í×fÄ!ûŽxœ¬ª¿y…"Mh¢ZÐì;CQÊñùaYÛ'…R%ƒp´©ûÿ¶ú•K®fA}¥3¶ *ñ“–Æ ÁUGÅ*ãÃpÆ\4W ÊBaÓAçÈKàz ûu£s]E]ÅÅÅ7ìõ¥ ´Ô®Û—+’û”°}/‘—®32Âì©Ú­u¸iitr@iÇœhAãŠäž[ïn¡“¿†WK„&xkÚ÷0 ßjN*̵N(µ¸€8‚´’ hå ½ÈFÇãùÔnu˜×ɹ¬zÜ+Î8Mv?•ëøç‘íß U˜¼w/¡´Ø¶À7c»»À#MÔ Z"O–qòñéobÚ$X3>µ¹\‹Nç'{¼‘*âÏH¨®ÞÍf¶qg`H\ • Ïû•†î»s=‚í?âÝzWGLŽ™ÜÄEï”ù• …{‘¸?ï|°ñ™1¤deþ"ùš®î…eÀfüÏÓ)Yn‘QÌOÃÛ2çd)¿#œîý—f‚Îa5Ž;ڭ鉵åRÞÝfqâ8Jî®5<dꓚ,Û?±OD–š8Á zLøta§­ÅJ²zaÚ¢ù ”äë•)æÿv™ÐŒ>¬4^Þû:Ïð®“Ì«¢§Ãùí XèI¸9ŒÑØ-=æ.}Ò(“à•¸õAšÈ&óU5mL´•W¡›Ä¯,!Ïë(j©ômW[^Ù'XøŸ (úûì$uMY9øxùkÜnƒŽtŠÖ1…‡£¥²÷/q‚mÎl£úæájG¾TE.•KüdïßHR pù¶•Ý¡é Hô´²™EjyËa6,x*p•jÐ*¶#Qô ‹âj¼³8Ο£$:îê¬pʹxÊYà¼))rP!ßÍù~ÊÈO­æ')¶7§7`jî€=8͓躟&dÙ‡Ž§|e ã¢6•®’Á¦a›Í' Æ4ðz½Žé3Ü@Q£Âô’˜XU;«FœÑ1䢌Jÿ÷\_ʨ&[åÜvxÙ<'û'ˆL¿YÕùvH±c*1½lZõí¥Ø»ú´ ¬°ZQûâ’ú›2*ñµÖ^Úí™a»à:þ’ /÷-äh&@PpòIF¬ŸÐiÎý"´eNèÕ„Äsz%ÕÑZÄ*æº¡É Ííƒõ'ÈZÐPŒo/=G£5…š}íü ÍlÕÝ7¢¤ßP6·¡­¶ 4íÏö¾E‰À<Ý ïNòéSÃâCÛLåw[Tw¢³~:ÊWìÌR¬YMÔè© Ò©äŽ&µË¦T# £³òžÌüãyC ž¢a•~ŒHÛu±é8ë žX¾“Õ³•Ç—cŒ0³ÚÓí4+_ŸnPQO^çWÐeÁyðuI¢( ×0n|i^Ý)¥›Ñ2œ¼r!èÓ±Ød@ÕiÿÞÙâê¼CI‘ ;¯/[µ€§K›@¡%j-ÏZ+ö)è­€1.åùOÿŽÕE»…$uþM1÷ÏLR±\QH;¦Åð^ ÁÌè£~‰ÏÁÜã¨ÉÜ*“Îå¯KŒ;›Åü”ͻѢÒf^º™j]µcÉ‘­B¾š %ŒQÝÀ—EV’¿Â¶`CÇg;c Ø9æŸÔ.)|ÿH•ÎEØ]žýýJ²‚w{Û¤Ö¬A{ánë£Ï²1pEN-Þ„Ez<^]  —“v-2r®° ž³[¤{é½":5×âÔúgd2%6±¹s¥^æT¥­ÇÏ5[@.jÌþ*ÞžˆÜ…RôÑ8Aï–Í{3sºµÆ“Pß|‡†ÎB—\VH*]Ðà®+cnúâ9d_®ÅäsÎΕ;‘™Y¿@‰¥HdqHUË%SŽ›Y9âç4Ÿµ"n¼q$ÙEï Ó„ù"€Ï¿ÖRQ€ÆÁ;4Ò›Y:ÐÇŒDŸÇ“nV*ß’Ü#™…ì<®üƒŸ”è)b¯!àŽ£áÖêë‰xZÇ^c À–íh='üByÏjRTš˜žy§c»ÓKß²‹ AúÁfsÙðööTZ¤àÝLN÷Ü{ÔÂu~ÏþúÅOŽ£JLòk)\j×ûu?˹ƩB›¿ëÔ¯éYÎúÁý|á…Ó U5DžRmœh÷¢ò!´N+cÒŽ!Éoïg‹>¸Ü6F‘" }ªý=flMÅ"Ê™Ÿ eø@®¬ö7c¯Ë·-ëfCr¦ºÓ3*uÀ²97¥Kˆó¦ûÙÅ¢J§Úè¨;¯écÖ7qu•t5Ò`¿aºV´‘b¡¼áçØeg¿Ç¦«8œûñp†lY?“öhÚui]Æbßȼ„a1¤t¨ýâjûëÀjnP7º3¡)ÇPèß´g&)¼Yâ/ŸH t¯Ðʆjü€D£àâsÂnö†3’=¹GÔªH+ŠÏàq7ÛFåø¾ TçøÞ¹@Lº\ÁšcND¼{Ý/³{<š“AšR¨rÛvÇL"©uéxùªÙÆ+ôV¾(¨çqÈ ñF…«‚¾ù2vpÿÃQ·¾ªF>Ü–L»_ƒÛ5‚JOÍÈe;]TÍ>Ò± )ïJô!4t¤l!%$è¾×ø:y]û×7Ô;C©EÕ_‘šDœ’÷ëêë°ŠJJHMˆ§|í¡k¿Ì¯4¶Ÿ4o(.°4jçÄV9Õe\ ’ø8WúÎ.z†Zß“cU}’¢ÕÕvö1<¯KææO³.;lº+.Ú(ˆ–ül†‡ÖXoAå‘ Ô— a·“ɼúâºÇÀ1Á2W½!Ï·¢Þ÷Kf"“´z}Š%«·D÷s§%Ë—¯[ŽÃö³õ±F8•Wé5×52Z5†S8³‹}Æë¤[À/Âtd·aŠ“ “ºókDFUzÞ„ö£r­ŠkFF/×ôبŠ\TïŒC ÝûÀ³PÁUó ĪT°†/WQ|B“i;TÁN—ЧE!YølÂ…Ô+“"K€(Ëàú³lŠc9 é…Ó£ˆÏ®‘lad™Ô.yªGúí®Ò FÚlZÖ9ð)¾ FJ(éEtñÙfsÛøX‹øJ,ºØŽÑ|][ÿÐâŠq;)ÿzX¯>7f9Cuš@bë"zWnò~K^-eeø±§¦Ï¥¡Þeeñm¢nt\·./‹ñ—ü)Œ&Hk!â<ÝH O¢ÝÌ_]{ñ—©æÖŠ4ã?˜K\ž ÄE*ï[¸ò¡N{ñ]á´%- q M¹ñ9zæcØsìÚd ‘étsv˹%<¼a|}û†aˆËµûìK“‚t'ˆë~tÚ'Ì0~h„¿…dN¿ TÌÐ0z?T:Ét¢usâš¨Š›/¿H$ÚØÞ+íJ.e-©óK7`4˜°ú™¨}+T.dÓßÚ—[¹wÆR¬à£ÐÓÚY¶@¦áßfdN-Ât=Œ¬uhY’߇ƒ¥ÕsB½4CÏVó,kT¼xß&—’Wj?¹,ÝZTN…}7Ò©À„탱ˆäTÔ\ëÙÎë;2lšHFUÇÑÏs©Ùëòùœ; Å\YŒßÌÜ»f(ôõ¯Âä eÁuo×:Ùìb›ì:MI°} Ú‰Ü4©{—Vðâ— lz¢g Âì†;±™hwÑ8fÕ¢†¼ ÏÒ D‰Ô¶xš -Á¯àKã–gâ±âÂÄAþbxH£ýbl±h›à¥ž’þ`Z„„‡¿~-+R_ƒn!µs—óSÍ?/ÅœšúKÐ/œ_FA²8™`ÑÛ0oêêQ‘0O#ü¯…¡£_³hqé´8ÛlÓ £®Ói±‚qé5¶¶¬Z2tdr9väË îÃ*У„¦JôÄMv­ò{‘ ´h„17 â0ü> endobj 66 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /GVCCYO+CMR10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-251 -250 1009 969] /Flags 4 /CharSet (/fi/comma/period/A/B/E/F/I/L/M/O/S/T/X/a/b/c/d/e/f/g/h/i/l/m/n/o/p/r/s/t/u/v/w/y) /FontFile 67 0 R >> endobj 90 0 obj [556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 278 0 278 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 750 708 0 0 681 653 0 0 361 0 0 625 917 0 778 0 0 0 556 722 0 0 0 750 0 0 0 0 0 0 0 0 500 556 444 556 444 306 500 556 278 0 0 278 833 556 500 556 0 392 394 389 556 528 722 0 528 ] endobj 89 0 obj << /Type /Encoding /Differences [ 0 /.notdef 12/fi 13/.notdef 44/comma 45/.notdef 46/period 47/.notdef 65/A/B 67/.notdef 69/E/F 71/.notdef 73/I 74/.notdef 76/L/M 78/.notdef 79/O 80/.notdef 83/S/T 85/.notdef 88/X 89/.notdef 97/a/b/c/d/e/f/g/h/i 106/.notdef 108/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w 120/.notdef 121/y 122/.notdef] >> endobj 64 0 obj << /Length1 751 /Length2 1203 /Length3 532 /Length 1759 /Filter /FlateDecode >> stream xÚíRiXSW†Q#†u„V YÍFB$ h’¢²²)Br“\7  „4à† X5ŽƒF*²ˆ²LkÑXÙAQFQ\@Š´gž¡?g~Í3çþ9ï÷½ç=ï}Ïgc´Î“‡Ä@,D„®#È àíHd gcã-†8(Œˆ¾â ]]ÉÀS($@va8»2(dœ ðFdb8.vÞös$:ðBb˜Ë_ 1 .G‚. ¡2ð@à܉$%AâdˆGÀ‘É€sQÅÁ"qÎ(ôež$áS+'a¦€fÒ`yˆH <(GôC°» ÌÉÃÔBq–D ðãç䱌~×åaì}D˜ A!1ðExX´ }´æ ñ`‰pa×å`®§(NÒǜĂ¥/F¹ñ –#H‚æëˆ·ÐÛ¼"3È»Wˆãükη8°Ý&Kø§èw“ÿ…±lİì H$2FľO»o\Åq,ÂÆæ8b1G†ÃæC4°‹ `’HŠù%DŠX$i ãæ“ê ˆˆš+Îc ÑdÿþŸ¼¼é®u:XGÁˆd2…è4RÚ¿¹±¡óã‚%ó ÇÂXŽ$…¸¸÷®›‚ìeI:ól{ém¯¸óüª¯wi–eõæk ÎÝÙœèÐ_6]¦2Á,±L™Y™´ïêî­-¬—™‰yÇ{fG’£GT©?­ ›PùÊž$XOf\ù¡ûÍMÛ¿³¿¹¤ ¼¨áÔ«ÆÑ3v_m{ªûW+­ºÉ5u'.ô0–JœýmÕZg«@Ãã‰%9Ôì¾ÂËûÚ²ÒùÙz—#W%ÆÓgõN™x{ùΕÂAýøó Êu4z6mÈçheù¯^¹jýÜîICG"F»ñø ×sR™+?¿Å®è÷Ì¿ûh?‡Õžðtóµ¤×ó`“m¯ÞZýÝ9òõ^ò÷ ž½˜íç±CùÓæ–¶Eò%wî“BLáai•rbµÝD…â¥ù†a£?}i›¨ö)­›ÞFƒqv5¨Ò0ú–ÖrŸ™&îSlõfïœûߵǥִ"QEº¶×Îø¼£Ÿ§u¼ÅEQ¾x6nÙô ?ˆ¼ØÍ=‘{†²ÿ¶bUè­¥¬Î3™ÔŸs¼±_ôÔ­º.­Å´Â;y×ß)ë¯Ø¾˜fö|=©ÑÝ2‚áûg5>g­1aH]ˆ¤Üƒw3úô}è-·Ëõj‡Ëù©¾þxòè„­F­Î¼Xòpôµe€wF•ž±Ú¨­pÔˆpCåQ­Ù˜™QØhOÍ.fFV_–uÖhXŽ•kÖ·–mÝn*ð€4á?ñÑJÇ*•ɶ‹f>+}Ñg³a›Wš^Ç£Ñ{›+ÓãßìÚxzë’Ü!xO[VÄ5!«)x5;79ž"Yõî¨~½æBh[à[ªAyác&¿ƒ¬-÷¢VŔ뗹Ō>t•í¨Ì a”ŒÍÉvˆ‹V–dZD¨6¥/{í¿Ñ&d/é”Á²¾r7î¦îZ~¸_„vi3•% ¨Ç·îAt”¥÷¾Aê”û£6¸Hÿ–Xšâ4>Ùgí´süTî«¶‹‘Æ\×êºdÝ2zhk‰M½T0ØÔl%»içl{˜ö´Èb±C{íéð꩘՜Œj_Ö^g¶MJm ÛaKO5ðÅòXÒÖë„CÍö磾¬yXswþmÕ£{{Ì^ýÔt¥) žŒ:t†µtjx 2ÆŽìŒy¼äê.m’ËuŽ!Û â¿'<¿Y¯t$F·í}@»|RQñ²µâÙXŽŽó^ȯ–ƒOŒì kÇô˜´6üþë¥'¢9fV7öÏp‡TšÞ_ed¦uiö|†?½¡Ë¢%A'Ú=èfÈ•6­Ors~Î,ÊXãÌŸ5ÞWê²ÿðTVÜ—9»´+Rc&Lbõ†·0Ù*¿c0ÿq€“w}þÌ“g¿˜íÕ‰4¿Æxg­Õ#3vYlÔªØÏ è¸t¶69éÙÚ¥Þ(q!Ûз_Û·9ø*TA¸XÁ´ýî3h)IÑiÎÝSÖEÜε˜Ø9嘚9­HÕ¸Ÿ¢É÷Ýïk˜ÙåÝXçÇïïKæNˆKUÆ+H k7„¥¸5›ÒLj [6½Çǥ榙­o_Ôm~âÀ¢»ªùSIvÜì_.¹ 꺖ãjG‚­óR,œ*Õ,•‚]§< srwlkÌW¦“þÃ…û¿Àÿ„WqÄ("äˆwâ~o‘ªÐendstream endobj 65 0 obj << /Type /Font /Subtype /Type1 /Encoding 91 0 R /FirstChar 49 /LastChar 50 /Widths 92 0 R /BaseFont /ESOZBV+CMR7 /FontDescriptor 63 0 R >> endobj 63 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /ESOZBV+CMR7 /ItalicAngle 0 /StemV 79 /XHeight 431 /FontBBox [-27 -250 1122 750] /Flags 4 /CharSet (/one/two) /FontFile 64 0 R >> endobj 92 0 obj [569 569 ] endobj 91 0 obj << /Type /Encoding /Differences [ 0 /.notdef 49/one/two 51/.notdef] >> endobj 61 0 obj << /Length1 751 /Length2 1206 /Length3 532 /Length 1757 /Filter /FlateDecode >> stream xÚíRkéVqûݧs“Ì‘øAk©ÌélEós^Y”v× õ‰K¥•q”Ω×zVß9\‰oÌØ*-w––jŸØpÁiVî`U~´}ߤ]”z3ý †6‡ÞÜË1nyo‘û}šÆŸC©z7.ÏŠÂhƒ°Õ¹æ±ÙE½Y-LMR{¹t°íÍU·8¾q›T©òܾt¢¹›~FöÙ"¹ÚwþYVŽÇeÍéÌÁ­v`™»êÇßÕaSƒ)Ö *PCŽ'sªàså¿hUüz~Wµ0`ØSRyÉAçM–qœ·”J;öbQ«5]¬bÛ?öPQ<í?T:§K.õ‚údÝç³ÅÛ‹»ÞÜÔ J —ºÒ2®^¾c}ãb¬ªN‚ê¾Æ¸\ÓPÛå‘ú’À„Dè˜âú==s¯âÒ›NjžÒ_üªàíØY‡OHÛ~jdÞ}–°½cS~ñG­_t6¸šª·’ÕÉWeº™/©–JhÀygÿ­s¸Rãnê¸HÿøŸ`¡0b\&Fú;L©Iendstream endobj 62 0 obj << /Type /Font /Subtype /Type1 /Encoding 93 0 R /FirstChar 49 /LastChar 50 /Widths 94 0 R /BaseFont /QZAZFH+CMR8 /FontDescriptor 60 0 R >> endobj 60 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /QZAZFH+CMR8 /ItalicAngle 0 /StemV 76 /XHeight 431 /FontBBox [-36 -250 1070 750] /Flags 4 /CharSet (/one/two) /FontFile 61 0 R >> endobj 94 0 obj [531 531 ] endobj 93 0 obj << /Type /Encoding /Differences [ 0 /.notdef 49/one/two 51/.notdef] >> endobj 39 0 obj << /Length1 822 /Length2 2016 /Length3 532 /Length 2612 /Filter /FlateDecode >> stream xÚíR{<”ùލ5.ƒHäò¦f5ns1ãš2FD‘û5—1óÃ̼³cc\º±%…FëR±TÊ=­[«,QY)›Kj„ˆ•Ë–[gÒîésÚ?Ïùë|Îûûç÷}¾Ï÷ù=Ÿçû"v8»(P0h 19CŒ9@tt´Ç`ц!D6HâÐ ¦ ‰š33cÀK°&ÚÔobŽÇÃbñØ´P°›ˆüD2 M#“˜€#‰ 2DdpƒÈ4Ã3t:àúi"p#@v$H1„a0…FæÁ` C}òdϤB€Ég˜ÂeýÕŠÙ"SÀîu›H@d’1é<€Ra('Hô(òòß°õµ¸-—Nw"1>ɯ'õ·>‰A£óþd@ —²Gˆ²™_S½ÀÏæA ËøºkÏ!Ñid3„œ!÷§EØÒ¢AŠ3C¨$z¸ŽƒLÊ×NDù­û@yÛ{ÛzÐûsµëMgÉqç±@ý…½^c¾Ô¢Ø´hÀmˆFcDDÑùëæÿÕcû™dˆBc†X¼1@b³I<Z$…Åã> 1)`4F‹£ ™G4ˆ’‰¨öi¯<€Y4:ÄÄ|ꬃxSÅí ¢|Ìb0HÿB0hÑ(íK‰1PœõòïiX[CÑ|#4`€Å‹Ü¡±Æ€ ÷oD2—Í™œõ?N”é_5•&ZFƒdXD¶8–Y“T¿ÿJw±$2B=ûúÉŽ†Äªl ÃÉ! Å^vm—;¨ùN!Q!ŒV"ÿÃÛƒe( ÿBµ†ÛÆwC%>Sh“UBæç¸mž!O oÏ»× g\>=Ö¯%dÕêÍü¶sa8²A²âÐƤ@õm²DÑÓ¾Õ¹øð„ÎýÒY”£?Àüóê]=LJÓ.MÙAW þkí*Gr¶¬õ«6ö„Èf›ÉsÜØwãw?»Š 3»‹ZIϲZb\Å4T'Œ™5«Ê–æò2ÅÁНžô›¥E$œÅ2püøbúýañĺåËrY½ˆÔÖèó­ ¼6¹›Ó7ä†ìQnVÞ³I³š°HW›Žzò4VZa¤ÔC^£(²£´„&˜~lÕ'ÌÉ•æ¦Ý–ÖŸŠÕÙs¥p­ÉZ$T,£œBÉGÏOx™x&Tœüîa£sô@¯PQ0?ZaÛŒëòÑUŸËÝžëZÞÓDÈÙ_æ˜ùDí÷ÙUÄïGVæXóÕŸ9’¸kòU¬#0eJÌòܨùñ_°²ý!nä‹ÂK(^~Ö)òL&ÿ¨Ìåê*À¬yoÍí»}rßhäßjê3Zª¼Û¡T©ÿÇÑ#+i­·•ç`!–¼ÂØ7>ØAU´§ÌaÙLw~çQF¢G¥¹cÄñ”§A¬‡„¼'ãnñ6Üqøik°0dô~Ü…ÊÌL&"ÕÓd¿x’þXcër,Tûk˾IFÊ×gyqQ}ŠÁ˜–šŸ„?•Ò=³?yOQ\°xÛ.ãàK¬Ïâ$má¶Õ”\IÚªcZó°*W(LG¤ð7W©(Go\i¸˜Wùþìt7¬óõK©Ç»â­f䥈 FHNë|¬Î”"\ño¶3¯Šq‰Op<ßV’ &£yˆHvù¶@¾@-Ç kkÉÍÛr—NÅ5QÛüá:ux×c•ìlÇÉÞÔ6K‰ø±Ž^Öêž²—æh,Å|‹õÖfR56ƘdwL´\¬ŸKÏE¦tÉWr~!}»[çRÖ#‚elK,ì}CÌSˆ8Uj­¸N®ò~:ûþ“víØŸ-³ÕMj$„CÚÍövÿP$ ' ÊèÜÜæ0‰”ä7÷Ù*ðÒð®°ÄbLS}K|ÉÌÚ¦³k6”uDC™¾¢&‰™x°möøL’Ÿgï«óÚE‘ªh§=†^¬êœ›[c;ÔÙWuî>K;ÖBÖi Žžü¨R‹ÓÌY d*v_+®Wœ!~°œö«ò‰KêÙ'Vô¤so-Ëú~;f\é^»Ïá¡íñÿêóŸå3³›àˆ%CwOø ˜y€n²êCKï¨å—¿d¼© K°»îÁèùõ\²ð©—$&·Pèñ&–<¯/ÝöãŒ2otÇ©}N¾´•H%›];@êû·]b#×x¥ž Ù郔¯«Â”]|øÍ·œ¨‹Ýí÷åŸÓøohÂS¨0Uƒ™,HmmëÜÌvápK7‹¬^Åu ÍYA›>^‡6¼í²{[½"g¿j7Šzÿ=\ð{óÑuJüÀóòï¿9 õËëÇ1åΖ#œB¾ÉÞˆ²_ÅHsÚþ9#OœM Û0/6ŸKîrá§ï§–r³Ìö/d*·¹ù¡ÿÃöÿ 2$±9ƒÄ‡ý„¥F7endstream endobj 40 0 obj << /Type /Font /Subtype /Type1 /Encoding 95 0 R /FirstChar 15 /LastChar 116 /Widths 96 0 R /BaseFont /XIXFVH+CMMI12 /FontDescriptor 38 0 R >> endobj 38 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /XIXFVH+CMMI12 /ItalicAngle -14.04 /StemV 65 /XHeight 431 /FontBBox [-30 -250 1026 750] /Flags 4 /CharSet (/epsilon1/period/comma/i/t) /FontFile 39 0 R >> endobj 96 0 obj [395 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 272 272 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 334 0 0 0 0 0 0 0 0 0 0 354 ] endobj 95 0 obj << /Type /Encoding /Differences [ 0 /.notdef 15/epsilon1 16/.notdef 58/period/comma 60/.notdef 105/i 106/.notdef 116/t 117/.notdef] >> endobj 33 0 obj << /Length1 1147 /Length2 6026 /Length3 532 /Length 6763 /Filter /FlateDecode >> stream xÚí—e\”]×襤‘‰¡$†¡»»¤†a€™¡ah$¥TºAZ‘Fº¤»éî%÷ý¼ïs{ž÷ã9ŸÎïÌ|™ÿÚk¯õ¿ÖÞׇacÒÕ瑳q²†*;!Q< ^8@AË@ Äñò°±)¸BÁ(˜RŒ‚Š@bb €œ»$ à‰ó ‹ °œœÑ®0;{€Có¯$€ê ƒ€‘-0ÊЏ«ÃúN…æÈÁ὿v¸ô nP×—P^`ƒ ÖP;’ø—‘ÒÖ ò¯°»ó/½„ººÝI8î$9wŠ6NH8`µ%j;Ýõ‚Þ™üßúÏâÊîp¸6ñWù¿§ô?ÖÁý_NgwÔ åduEþgªô_rZP˜;â?WÕP`8 "‡´ƒC< A^>ÁÅanÊ0O¨. ±Ø‚ánпãP¤ÍšÜMïo Žª–Îs5®ÿ:Ö¿uÁ0$Êí ðý“ý7ƒþá»!¹Â<f|¼|| »Ä»ïÿ²øfJHˆ“ ià€]]Áh¾»RüBBo†´z žwÆ@^¤ên àn2¾['W‚¿NUP´G;ÛC‘Åÿ ß…äþ!Páß$"v÷Pÿ&QPÿßtwÊ@ð?$ ZÿCwû ÿ&hó‚@èÈÚþw]ìþ@Á;ã?ðÎö €àü¼Ó@üƒ ; äx§áôÞi8ÿw}]ÿÀ»¾nà]_Ôx7 ÷?ðNãåx§áñòßixþwè¿ñ^+yy'Ooa¿è¯ˆñùþo‰wWW(õ÷‹{w9ÿ›maw÷ õ„Bf¦œ ÁI5¡ü”rG?âpºÑ¥¶„T§Hðî.HOºÖŽ@NÈBÈ`Ť‰û%@[¡¥G5r>=ÞúÀod=Ä”œïSõq!»æ/0{³ºÛ 2^oÎ0®9×rβœ-¾lÁ)Ó܉ä<ÚÀþ0=u}êçè?´4C˜lòžH`‘Õ¨™5ÜZ|;ðkOÅ)×i&¿—Ú<õŒâfæQûü¸ãwâ±È,-¬©¢#3•²„CŽ]à¹ïÉ>gzºX§së­¸•[Ò¶µ—¾ó>Kµ¦žÍ±ì­B÷¸æ"º¼n&1iC*V꬀Î)íö¾b ÔWEË8³ŸœOØrb¬{5çí¦`Žm¶÷£Pc6yõŠ}¢ÆK‚¸¶p# àU}ËDºi`þ×:»ìxDö\¯ÄÃÄ"láOè{µv̓K÷ TÉîI¢¯]¦eüylÝ·ÅÇi «‡bÎ_ìKmµ½Ü=¯kqÕUuýŠœc2$]¹Âkì{Í]øLfýl_:]f'ÍOsê„¥n-D…>¬å|ÚnþÕEþ›ò䘡‚¿¥AGÐÔB ‘ò¤¸½azŽ‚Ê àý[RyÖÛš)ÑêJ8êtÂY«D¼ÜþÆ… Úªªñ“7ꇂcò SÒ²Èáh8ÎëÊ›ïü.í1 IZP‹³[_¹}ŒߨˆpK§‚‘µñ¶ÿÿ84ÕRâþXnƒ]£º)‰;X"[‘1Ð09[Õ•éœçl|Æs{@²6vá#®¾É’#y½Òi‹SÙ>‹‡,Q|³ºRt¸%ÄU<›eôðI,© ÛšXfùýì%º¾ö†Ä§ÍxöŒpÅÆ™V®M§ˆÜTõôþ§Â"i¡¯ DœM&ÚýÜ•~±73f&æLë­Ä…¬“¸àïËú¨Œ‡•þî;Ó6Kûƒö=^Ø3SSîeøØXsÔª-wüð{“èÃÂc¾¾RB#‰öx¥ìS#Þ·ñüº^þ-l~•-G>¹ËÌ"LDLHd×É“„ÃNôðÔB^V-õšév'& ÷”Õ©ý2n"3÷b6$A_Uyh¿{ ïÓ©QÞÔà Ž~ƒ˜ÏBŒæ &(qþ”ñà—Áaz'´= ýì´üÁ÷ÓahÒ¯˜rîdl­Õ¯ËE%7%.=êÛ,t—ím]vê8ßÍÁ¹$ûI…d«aÏû<©>ºóÛt†è¼.ªÖZ5AsÇáùògn„Ó+Ì~‘ö1ßãî´cÙAÜž6‘'ÕŠ#ín’·ˆã#óÉºÝ ‡Ôyk/Fkf³TQakñßœ‡[±]òùÝRÃøôyUüºg„ÈYÖAÎÉ•jºÜ@–ÇVó‰Œ © 5¹Nà¶‹Ægî’…=µÞ…>1GâÍmüm[xBÇCB$Õ¹IøÝUó¢ó7ªlƒCƒO4¬£Î? ¿æÖ4kdù‡H>)þÞX-â)Õ¢ö9_°Š„*3ÀÄ9vDR¾Uia¨™ˆBܦ­lEPTAþ¥«Í¡°Ö# Ðíq[c Ã×ùPüb<ÞÚeéM!Ns óEfÅitL…Yˆø}Ç-8‰[ãSG^¤ÿ9Uñõå_}Sª0ß¼’Ä Î,ÑGüa½°Ìã,g÷sM¬E E1—ª2`? e*Ó”~»yÒxcìVŠIL÷•Þ†gå8¹,àÈ9T 6~·‡¹ Æ=­OÒ¶LZd®¾2¬Þ/i˜¿êo2QçLf—°lÒóØìU ‘@~»óâË”:°ó>‡}já6ãaÿÕО¬sü“?xà‡DÒK3†‘ræ)Ý $eê@#™Ž m›éö.[äk:}AV¹¶½‘ÀÂFò+š}žÝ×uÓ§&â”CØc@ù‰uŸ­5Ì”Küa‰EÚVXñÞ›^(Ídr¼¦ÑB¹x¾×$w[Ízé Ý#2XK䤭¼›Œ6–^ÁJй§§D¾ªRê3G©] {£Ï<ÎUö–kÂâóç‰@s*mGü¸XÝmªšM>åU:@3ºÓY#êžÇ>óÐW»úÑàœáA_Q-ñÂB¡2óxˆNQ ù¼µÄÕ…2?ˆbJ=žÌ4ë¶öGéÑe#‘ç¾ ¿[CðxMΪËWk÷¼¶ôç8ÞnEêŠoiñÃµÎØ­²®o²÷¸Â±TpIkËsvÆŸ¸OP†©¤ÛD>–54^ <>…8¦`T(@æ³Ú2ž}Ã8ƒÂõuÖkç~>8Zÿ…D¯m1H':YNe'˜{-òâ¼h›ò0m3±H!ùÑ;¾,%¦&ÿ«òÕòâ*ë(½TÁæ¢²ßÆšÇëc{ë½uÓÑlxäP·õ›=ã ÄVëî;"KÊFÑf7áy‰ÜȧËX}FPíáðÉæUª­MÂÁ¬6iB‘]—¯Rê_‹hGRu\á¼ë ";¼›%ïÚî¬uë¶Õ»Šl¥Ñ¬åO•ôyÞN B›KK.†i5ÅR–rÍØ'§áržÆ²ÀC1L@ýì„”iNôÖ(dMvçØ>¾ŽÕ‘gSzÇ¿¤sîÇ¢»›:qƒƒNøÊçÔkš*[L_“’i‹îŒÁƾ¢D¹Ã‘ýøtÀÂùw©”~ +÷˜eÁBÙè®Ýxµ}_{–¤ŸsDæ×o‚¡ƒÐÓ#½…Õ%‰hòK)œ§øãaÁ ‚.׫§J·TçÉb’?iôæ¿ÕßXé俆,0ÊÛ„ë¸%t2²¼Ó°üMüÁe+3=îËpQ(ºeÿˆžkt×Oð‡+y`cÉÚÌ ‡/S§ ˆ÷FÅ­…£µ)e '@t¹õ®|cè¥u iŠì¸·¢ô4# zw'«I»Ú½ùW¥|¥b»GHƒ@PL'ÉïQx£gÂÿìApë,ÏAQ(?ÿºŽ^×j­ ¤G‡ÎIx¾{ÖunøÚYz÷é­(ɼŽ7][1ùû½Vï0±ˆ>eé«0~YŽl±Íó ,¸Çb™MJ;¶ÔÓ >ÝdTc²à£kµÕ ñŨ×èØ±a4(æÞ`¸ƒÎN»œ{¦r‹¨Y¶9Žö[a;¨å¤QwUéYÀë’¹‘(¾e`+‹>»m,êeÓ³¼ÈQ·“Æ*RjW!;BõOª¶|>Ç܈k¡ÈÜØ—`d^ *‚Y-†9Û)ÑõjEÊ»ô×Q ]YÜ:0“Ñ ®Zÿ.cPN'Êé—uÄHˆYäS“”i—,ÌP6ç642(ïëÎ?dJÇN‰ô¼´ bn.Ñdì̵3H¢ÇÒƒ4xš%b|Ç-›O8\' ìÜ3£¢²7{n¢ûð¾×s;A ü×Äyidµ½ÿ3‹×7‘J³(ÂéҭǶ#»Ï^÷èÍöj×»ÖH»ç“mÖa8dXÎ&°Ñx%Õd¾mfÓ÷ü€êØxr†šÎ²î¬ÒÌf¿ŒWh{¡é¸«5¹’ŠRÞ` jÏpDiíõåJ_‘(‰˜µD})M[Ý÷yGËØµúÜ]ô¯µ3rN㉷hÞ«¸Xi8¯Ûºà<–޽eÛR^ éô`“‡}QcJXn¥û“üfh¿q-íæËªã¹~OQ†3ÅÇkò,YÖúà|¿U„‘¸·áíâ Y잤ÂêR½P@£”!˜¶*^ú…ÿ©z§ù\Ápú»õ¨Íóè³ÿ4Zšƒ ýËÎ 0Á½´'DìÔËe *³Zø„98‚S©+-ßÈ—5}SÂwžø†}³è`ŸÐ2±‹+qøòl-^[Î#øíwÌ·Z‹Î+s1Ù¡åÂzH°ª‰aÓzµú‘ôõÛñÄ|ûˆçŒ?×,™dV×§S§âºÒnÊù‚^¬Ì¡1Ó´ã¦Q·t"YÍ*Úav"ÙdÕÂH&ÕhàQ”óiïø³ ΛÐW«¼Åº“XÏpºSyË© úæ~RåUù]S){&úÊ*TD¼Ü½.Ò¿uo’v.©,˜@f³,mäV8dóPz¯â@WÛú!E}Æ%•¦êÂbÚ›Q$„bìö£ïz£¼'|htUÙjã·VfÚ¼E@¶?øõ§Dê’ßõo÷Â~¢—Ìi=ÅÉW³ ÑŸÀ2àû§Ð©u9n°­j9KyQ÷4_#îotû¼^Mx¡Ë‘zdK±B4õ‚˜î ÑKå½íHÇŸÚæŠ÷¸fõGêê/´}Z0^&S|óÑž{˜'#©Á ˜ÊU}!óÉÙÁ"Z3Œïù;‚êøýƒä=.|Šï7X9ä$ôåÜ~v@{Sˆñênìlrû^ÄBuÌqëXURêûa4Ú=U½‰‡©¥!6ÌHʾÒ1™ñç6Î/ T©ÄÛ¼õ͆æº"’%¬Ç“%L.‘·q¾˜X›«¯šÒ S½*¡;ßâ’ˆÞ>§O”à.¬¡0”¦}RŸÈú(Z.Q{]½ç rëÅ?–:ª»\%$7ê¡E®”o›V˜1»¥uvÉ6ùŒ¥¿>=Æã¹·}Epdu$y¤!7^Öù=ßÒ´œ’vé3Òa˜Üì%a°.`ýK%x¾| _Ð(¡Í@ô[üÊN„¾´Êúìp<+CþæQ»¼Ùb­¶{¥˜´—¯¤ñ%Žë‡É&Þ/œ  Lž»&¦¥×[/âÛnÆÇìôš•'öWD¹¹æ…R¶Æ]yò‚ëpN†¬7ç“O„S¨)ÓŸÚß6lÖ´ãnZ1ú=¸øšÏ¥‹IQBIgï0µ„ÿôR3(Pÿ|ÌH+3IDœ" B|zl|:5¹¨È%õëèXÖ<–Ýìûó{…f\ÓÝò¯Ú) K͸žq\!´>óáO”B§VÊ™'ޝîÉOîKìAg7ñýùG´ÙW4×Õåsr$ƒ 2IcÃDŠ–Ò”f‚LJÓ“¡™4Ï–^äK~¿—´yLq=äK¯(aúI»®ÙKú¼ê)êMYL³6Éó$£}>“ËðÚ(Ët±*ðžF4¯a›8#†?ÛØ¶ÜW«D¶‡ÇÔßD ¢æÝU˜£ÓÎUõ¦­u –ÔH»ä&®ª}×/·_RrüèÍŽ¨ÞœÝ8tãï%nÇéK¡Š’’ý5ŽBÎÍ€2 w·p£%Óéì/f§¯t …¼à2¤á—¯stP(ðÝ´¢K¢ZÚt}¸)îÙ剱un•23ˆ>ñ^ GÑ?>Õ¨eÿ¤aÚ< —·–ëß–£%OcˆW¢¿ŠŒ#³Ë]+”nÉo\9¶!N•6q쓌Ïü­HŸ*‚¿LãÐ!ÈWk“Ÿ›ñT‡XÌ2]<̼קWùØeЛ‹žER¶ pÊNnu”O–¥°ôû2­Y¼úöìP=©Å‹U ¹Â¹…#G]¶p³Ä$ï·+¢¼XRt&®dðò »q•48Ë¤ä§ B?ÒâœÖ•¼êÁYê:©¸¬Œ,䓺û×÷bXH÷xî˜>l¾Lhÿ°F½Ê,=¸ƒàyš†”Ò¹^ÚâHJѬ¾ñ°Îõ“ŸÄ’î/œšv"ÖyÊ`:)Ï¿•¿g׬‰eFFÚ%dãËZH/¹ù(¿‰k#£&?€=Ǿ-¸{^{—©d«„•Óÿ˜ä:Kp˜ºJüÖy‚µûò¬óÂo fë&æ­Ø¯º*ù§Ôc<ìëèØÍTGfá§Ëöç„6¤/Ü ºùþ?ÿ¿Àÿ p(Øå„»:ü/×=eendstream endobj 34 0 obj << /Type /Font /Subtype /Type1 /Encoding 97 0 R /FirstChar 45 /LastChar 121 /Widths 98 0 R /BaseFont /OHMOUI+CMTI12 /FontDescriptor 32 0 R >> endobj 32 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /OHMOUI+CMTI12 /ItalicAngle -14.04 /StemV 63 /XHeight 431 /FontBBox [-36 -251 1103 750] /Flags 4 /CharSet (/hyphen/A/C/O/S/a/b/c/d/e/f/g/h/i/j/l/m/n/o/p/r/s/t/u/v/w/x/y) /FontFile 33 0 R >> endobj 98 0 obj [350 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 727 0 700 0 0 0 0 0 0 0 0 0 0 0 750 0 0 0 550 0 0 0 0 0 0 0 0 0 0 0 0 0 500 450 450 500 450 300 450 500 300 300 0 250 800 550 500 500 0 413 400 325 525 450 650 450 475 ] endobj 97 0 obj << /Type /Encoding /Differences [ 0 /.notdef 45/hyphen 46/.notdef 65/A 66/.notdef 67/C 68/.notdef 79/O 80/.notdef 83/S 84/.notdef 97/a/b/c/d/e/f/g/h/i/j 107/.notdef 108/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y 122/.notdef] >> endobj 24 0 obj << /Length1 767 /Length2 646 /Length3 532 /Length 1191 /Filter /FlateDecode >> stream xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž44P0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22°25çRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥r‘g^Z¾‚9D8¥´&U–ZT t”‚Бš @'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<8”0äs3s*¡*òs JKR‹|óSR‹òЕ†§B盚’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l ‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;|`‡èºùùûhCã,˜™WRYª`€P æ"øÀP*ʬPˆ6Ð300*B+Í2×¼äü”̼t#S3…Ä¢¢ÄJ.` òLª 2óRR+R+€.Ö×ËË/jQM­BZ~(ZÉI? ´©% qˆP,±,€é3'§üŠj]#K]K3 M††f ææ¦µ( “K‹ŠRóJÀ‰>0~Z&0LSS+R“¹n^ËO¶nÉš¾­meëâ «Xõ9žXûò&ûˆu³3SjƒMç*¦—,yµðÑÖ¾ÃâÙ%¼’­§ m‘ìõë‰û²HxÍÖ®Ë"&4˜î×»,^ÙÜ5÷Ÿ¶ú+ÏÃ…a3æ´>’¶Ú_ôxV§²ÎÍ/Êõ'x楼pŠZ¼ïû½kÜBZA“´”¤Ìo®`¿Ë(&^y÷ùeùO;ê§·M~wö–g€x±[—úÅ4;î¤/‰ßžpŦ•]¼¨øÌñà•Ê%Rþø÷ì®x#Û¡Ô®úñH𲊯]uÒÕ×O°‹_êxÝ»ðk?'×~Y§£w/n9þH¿¿Á}Ÿ¬Ì‰ÇÆ¿¥NhûMI7¸gÌ´éÙÉÓYOB7®7lÿÿ‚]jiÝe‰Ùs¶O‘uySU¸|·í÷PñÞZ=ïm3"ß/Ù}˜ûÚnQCaû+7ûÎçô;ÃÖeä[ºõÛ´}¯õÅŸ¾59sí‚û’Ç ¹ <’skc·sõú'ºýcë=øô^÷Ñ3gÁÀ7 6ÝçGî¾¼6ÞvfOÞþÕg/Ëši|o‡c—?‡ëŸYf«ՙ#O–xÄÌ>}ZnÞîÏk޹è¯c&§dÉÌü7­JiÊW†*އŠ26Ùg^7Ê‹m~uý¼Èïý> endobj 23 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /QDRNOL+CMSY10 /ItalicAngle -14.035 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/bullet/bar) /FontFile 24 0 R >> endobj 100 0 obj [500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 278 ] endobj 99 0 obj << /Type /Encoding /Differences [ 0 /.notdef 15/bullet 16/.notdef 106/bar 107/.notdef] >> endobj 17 0 obj << /Length1 1989 /Length2 12137 /Length3 532 /Length 13253 /Filter /FlateDecode >> stream xÚíµUXœÝ²¶‹Cp.¡qwwww‚[ãÐw—àîîîAC‚»w‡ àüý͵ÖLæú÷>Ú×î>éûõV=5jôx)IUÔEÍA¦@)ƒ #++@\QCƒ• ÀÊÄ‚HI)î4q±9H˜¸ù¬¼¼¬QWK €•‹ƒ“ƒ ‘ rôt²¶´rЈÓþÄ µ:Y›™8M\¬€öàf&vu™5ÐÅ“ jgPûç g€Ðèä4gBde˜[›¹L–ÖˆÌÿ8’u°¸ÿK6wuüŸ%7 “3Ø€l’¶hr°ó˜-™•@àZ@°“ÿ7LýïäR®vvJ&öÿ¤ÿ×.ý_ë&öÖvžÿ²wtu:Aæ@'‡ÿª ü/sŠ@skWûÿ½*ëbbgm&ê`i°ü—dí,eí4W±v1³¸8¹ÿ%Ìÿ·ð¾ý˳®„ª¦‚<ýô_‹*&Ö.žŽÿÎúOô¿˜õƒ·ÇÉÚ ÇÂÄ ÿç—Áÿ*&é`2·vŸN.€‰““‰'"øh€‰àÍ °v0z€`ÃÌL ð#ðžø,@NˆÿÌ“ÀüÉä47µûgå¿DN³ƒ«½é?C¶tø#s˜ÍAvv&N$n³#ÐÉ èàòGã0›ØƒUgðÖü[åýïBÿu$þGæ`'0q:Ø-þRYÿ[ý_ÁlàÌÎÿ¤p¶ý#²ƒcí\ÿà–Ì@öö&p?VžŽVÀ?½ppý˸5èCp/Îv&ÎVp'^@'ÐÜÈøoæ»wqÿ³Î öíbåü+\ÚèöWeð˜˜ÿÑ'¸°ƒõßiyþéÀô×C¼ÿ¤±·þO• \Þèü§u.p}à'W“?£äo™å?WðÏиÀdò§<Ø¢è›ÿC`'ìBòßÄ ®.õ‡À¥¥ÿ8‹âgQúCà,Êÿ&p•?΢ú‡ÀæÕþxÐêÜ„Æ÷ ù‡ÀÕµÿMà“ÙÔÉÄÌèò‡ŒœÝ,ÿçÌyÙÿýŸ‡\Âüwrr69ý™øVcþsÒxÁšþ!p§fÿ&Vp«æá?Ãú Áv,þB°Ë¿Ü®Õ_6cý‚Ï”Í_ödû‚MÙý…`WöìÊá/»ý…`WŽ!ØÕ§¿ìÊé/üç°ÿ…`W.!Ø•ë_våö‚]¹ÿAðûÙã/»òü Á®¼þÂÿžð?æËÊÆùßòŸAþßµ˜ÈÛ‘ÀȾ 9Ù8À‡œÓ÷?ÂÌ\À7‘Ë¿^àËþØÂüf=€fˆ?Afü!6i­a~’EÓ•°tb–mñJM}sÝHÁË v¥£òŸè6u«2ߣÀ¸?:G~ñQúø)>}áõÀÍø Ó«ƒPç:SÑsß‘ìwð)ZWëü¯3NHåÙ±ŠäÅßr.¿Ÿ¨ÐHh¯‘Bôë¹5÷g…pqëHeÚi†‡6R±“ª¡§ªøÌ¾îŽžœ³>ìgŽÐN¿zúâŠùX„Ÿôjm>¡eüúþ ò +.[iu˜XïÙâR6iÝù²±AX½¡ÓóÕÈ$RÙ’§Ïv—òÿØÇ¬GTcѧiuÇŤД™TiS"âz±‘òbfâÛ’›Xûñ4ó[É-Ü»"['™÷БlÆùœ1 «ê:Ì(U^´S1ï*¤œ6°ob²^´·Mö 𱨇ÉLöü=3|ï “ èð¼R~`Å5 ´V²Ù¦3°}oÔ± ÿ°Ô‹ ÁZ´¡ÃÍZæyR÷®Zÿà[í –ŸÖgú«Mî7œä+V›!ö7?$fJjÎI”<ïÉ÷¶p©^=È1׊c½áÒPç”ô–þ">M©ã¡ëÏÌ’ßÔ:SýDup g@gƒ»tƒsM§RkëÜ#Ì›W7ŸÚêéTU øéŽ.ö|‹Úü:õ®“އ–X²¸ßè*´s&ý2üã4ÛävN³gsdW'TÚïÛeÃ8æì[ôœ[àJö®;P“ªú‰…Hë±>çÒÛ&JÚÊYf£$œ­>©µ>‡Ù!È‹7‘X§þ”l¦ˆÑÉ“ƒ„éøMÆy’aôÙ¾p2_J¨K|k:ßöÒ…¡cÕ*œµtøá²áå0hÓKxÄõœïê$Ö#PLØŸ³1 5VׂaK’ÞGø‹`Âi%Zë>Ÿ[k;ù†ñNûí··ø5BÑ kÂÃÝ ¨ y…k1r"fŒùÀ«Éý{7Î ÉÛâØö&ŒÓ£i•÷gWÓÂÚ²A»:x±ì.éüV(Ö¿—ãh̸(Ý[µlS¨f¶ F/¤ïrÉä)ü’Üÿµ½nxÝ–rr¦'æã>Ÿ}Ç]TU©Lb'ÂꦺÄð°¢Ó«ñöúÄL륓Tö«ý©#1^!íGûGžís hÝ*>¤ßFÝŽ=ÝlalßNx´D%¨r2ÜËÝìx=S:Csz;¢‡¾ 1K “%@Î9…š¥Ì¿M±pÈ¥ì…Ïn”ÄSÅ’’}”ˆãX'7yG¿4„Øú‰bÛIzˆÐ¶Qô‘vþ½Í¢ë1·EΘ/­×‡|ý>V74‘N»ÞÝÏ;}C"ʲ„ù_Øh»†Åì(î_&ÞxK I¢ûC4µšÛ_XÐOÇJeÍHÕ¢µ´—Åëé©q ¾&9G{tÞÝC}pƒ×Áà…‹§”ÚÏéˆä5¼•úA„GB8.5<ü`ZêÐQºß×¾lmÉæÝqb’;@ÔwÔüÈþDrfê-ÊŽ'rعjËX-Krº¤§µc`Þpö$€5ä¹}Å9ÎJåä6Ò®iFÀV ê áœ;¨tE¸ô‘ÚhHx¥tIV;¢Ë–÷í{¬K'²-®óúð£Ì{1±=Ir»[{ÿʈJì¬êÝAÂs©+.“T{Šj¤ëåð³™¾bK<¢ù—ür‡úInf%ÞÁ0®äèX½!’Ö³ €È¤^@ßD·rVkÁFª Ø®þ¹Káè6[^7tì@Ÿ/âtÈM`Ѓß?ÙÌ Õè'p=ÄA€ò¸Ñú5 4Eó`ŒÚ–ASž[Â&þ`cíû¾›Tf bߘª•µ#K’j;¬ï$ÿù(Íéúš€pÔü£ê kô\ ·¢À¹Bf÷Ê~í«²Îù«žRîò,fQ€¶ZQ‚]þí¶n/%2z;ö‡mEoCþs †5SZÖPŠú+»#Y¹“0¾û/h¨l5Ë V㉺#tÔ…&aJí‰6ˆ‚›Âì…ˆH6ú®6×1ŽRކºq‡íAÄ$»'¤R‘a ù Ñé ëlÙT©QË-Ú/¬èÅäóã‚æŸ\Ø’Êõ\ÚÌg¶¸p¨PGZ[¼Ï\rRѪb?­¯Ù¬y0ª–Gíx Q— ¼cx%¢¨åCÞÛÌ„Fß^Ÿ-]–°§«A'j÷Ò]‹‰mì8’ZcX#¾%¡EPy…çy ·‘èQªÇ¶ýú‚­amÓ3i&xõYý«ÿ5 ’Ð®ãÆ¾t6ƒ=íRCc§Õ~4Aƒã‚‰G§(”¿gö3,œõuœRíñÛN€"ñ*ƒïjúN agÖÇ*+À7Ò»¾7oqu´x÷Ÿô†C;ãà(I£¬ü=NèYüâq’šª 'SL2{Ýš´ó´Þ¨˜’ÍQFaßAé½hÂ{Kfp@<6¬ƒ†`äÊd[(’Gb¢…bwû*yCÊçsCt²ÔF'è ›!ñÈìlÊ£ûó,’²¦÷˜ÃöÐPD1y-uÙüÝh~ã^Èã •{Úáйd¬ £-‹Z¾³¯þfôÚBM}kÏ U­q¡ [ŸÂÇf3k”ûP}íN%D5Ö¨FÉ1ò…SS5ylŽ« —ßéªë6­¾« Ã"Õ…ºð‰ ÝGI® –ðæÍUnC!0Rjdÿ·’Høwf/ÿ¾Šßéd9OÓ ‚º/såvenÓEûÌ#Ïë8ò°¾hÈb‰¨A)sþV7„i¢äåÛø.V`Ëë‰ÕP‰·/»ìb{½T³÷•þ`‘ó@DôÛ¼¢Ì¹Vû2ÔƇ¼Cc ¼5f9¤›a5á… ÜÌx*^齟?€¸qÂ\þ” n_( §çê¡PS=u¢/}°vD‰OÞ2O±›q φõ µ§q”²½è ÿöeÇp‰¶`iãYΘA[§ÝªI4ý"A¥ê,T‘&ƒQÇùå8WtNq„õŒžUn¶ºñ$«­Z¦`0NdDâX8ä}þTóØ£A9œ‡ˆ4ai]¯Ç¸³¼,Ü›§._ E~xÅV÷­hæ3éò¢Dqµv"¾ß÷L)¨møF‘EŸc4W†¼ŸÜØÂÒŠøä¼ÇF+dø\‰3ù.˜¡Ë<"s\’k§zŠ^‰ 7<ü3Þ2áÌwˆêuÌ^öDI¬¯YªÔº=ÓG ¸óÒ¬»Š\+¿°‘«¨·×”qkÒþNñg|ïµþk܉BqSK2§ÔÞ¾–¾Zrx¡D§ÁçC™ÇË`ÿ¸ ¥Ûç/^¼•æ%D_èyHe ¼¿Úá>CpMg$çV·¸%²ÅPr`6.Ž˜mAoZ.sÝ÷þÚD [Îå­ªšl1¸íf™=Ž÷m¿.ôpl®,ÝÃ^òi/‚„%u‘‚gáD滹@.ùR¾#lý9Î(Ç%½Fag©${üL©Ü#*ã/ÚûnfZÞ[ÖUò«ò$,ü !ÌîûlúŽ^KC«Õ\E‹Ð®}êÙþ!”äEï• Š5ÔOf å(ɯLŽ MÔyP¹¤in²“áîhµ N$n;p&îŠ<ÑÝÌuÁ)4å§ãsÜ@Âs43¤5“ö”ÉD@Ö¹)~Ÿâ–Ç2§&•*çáKg¢¬—|Žb‰øä>Æ* êSK•VD†,¾£yŠXŸ‰eRÏá8t<Û¸7'•y#‘Á¯%ŽOkîÒÂó×8`º#_€bHýMب—#+4Ö£œÃFº©-ŸLV“‰y»á¬Ô8^Û—[Ç­è1ˆ ,•È?LÊŸ¶3›>Ú¬›L‘l–ƒâ2MÚ e¬‘q¨3¥ì©â-P*GdQF™Góç‰xÃã¼ì.!?â:|ʵêð÷,ÄZiX¡/Ié ª°)óïå;[×Ú¿ì ËóÒ1‘¢•P­‚Ñ6ä”ÙÎø5'󙯱2^G~ •›¾-ÒŒ!?7ʘœYl]§C_yËÉàìKúì#«mAŸ jâÚC;µÞ>$\‘äÀòΤ¿f¢¡ ß»8nmçÏê±é œ|Ee¹ýÅÃHœ¤l0i×…èK|Öfãõ(Q_>ýèüµ~%DtØ£OõõVá<Òm_LœõÁ‚¼‹ç‘®¾àÔ¸uN ¢G=™KÚü%ùœ*Û%Gn’­†§Ó’ 51š‘<8n̹ô‡Ø–µ VvfÒZmü »VïM<(Oãb!—Èä)ÂUD•&¶ìµÇ?öˆO;Gÿ:#5pa‰Gìd OÈ×iú})AÁ®uã‡>Þ"Ρyê¼Wd€|pAH 1 ‡$Nq4 ¦Ý|3¹Ò.IP­°¤ø*dfkêˆØˆµð¶ÐaÖœÓGÍ·tž|‘µX§à‚ŵCvušÃˆÁ§þžSØU¢ì³AK ï4¾éh¡k²ñ$”x­™rŒýC+Í(È’%ÌV{"Þ¦ÀWsꇃ~×Ü8< O@D©F¥l‡±b…'ÌG±±•xÑKÍ•ç• Ú^ö›‰rPT%Àå²›©/Ç…ø¥A&a€¶öEÕ»3HPhëþN ököTvŠ×©VÞãØ³ðYç箘iصáË zó§ÊÈù,XZ¨¡BüÚlЕv âo£¯!âj¨¯JÅ+>åäû{_øì±©AͬŸàô´Ö?”Ü~®kŽé7ß!QoX\äaÏÎøôkÜ/ñ½¸×Ä2`+ÌY¥¿îÕ,qbG[Òfá6§g+î:/R¿ *$™ºaßFüo/Ã…ôY,¾¢¡·L~tn± Êì§dö¦º-bŒçéÛš$ØÛ&ÁÌ …ÓÇüJéok‡ 4»P·úÊ~Ÿr±Î„ðíþ,q}4稣%߯ÍÂV$ ^[†(ìN¾r¤·'H!z§£>:´½®#„æƒî•I1 û˜ÜZZ¼/·ƒv»á—xõûvÍl€Lüä;uæ9¼ê#‹ü&*¯ü{Ì­sÔÙ™ª¥ì9|ýí¹" tJ±á¡ÅŽÝ«îvÊÇDO¨yòîÃ1í¾QÙ•ÏÎ W–0Â÷EpIޏéM&ÒÔrPׯ&½7yódìJÒÅX‡ÂT[£¾¥› b>¬3Y£ )×cÎ>lƒˆ8’pï®5ùqs±²²œîœõÐ#ãó=†uOßlÌ s}`½E­än´Ky¢8ŠWœsÏÍd>²&Ô|vªMÚÒDL(fHb·5ÎY©œô× È'L*¾ HX{k‹¨n Âa_a¨Xõ%ù©i‘J‚à±Fnª† Œ ;ç4!\1ÂEœè1ëf•œäd7‰jË—µÛ§Tð£3›ÂÍþx8fWJLï©nDâÚ@txÕ…‰‡×ýÑ'Ýd0¯aþîÄ.ÕºƒŸ³…5£œd¹qF•Ìq8éãRæ]9¬š¸qaoq—ïd;$ rŽ˜Úž©ýlhc#êÏï„iÞ §ó Ñk’”cqÔ±&v£sO_ äüŽhŒÃ*à  m‰ºg¢ÔäJw⢓£qf|‘¥„ÅÇ‹~@Qá< ã4š-;#Èù}+h6ÒAÁ-©.º·~…‚áÿSŠÞ?@AðR¤o…Qp‚:eýH=‡8±íý-qþû ÙbRîá»_PâkGõUÔ<'Äñø‹»H¡ß±Ë7cfÌúXÄÚµ0ôp3b®–B®dÛ¦~›¨ZÜçm“‚USŸT+€ê¨hìYî ßéò,&¾Õo×T¡;–68b÷rÚxœQþ5SOħbœÎàl¨µ®Œ­ ÀùôõÔº¸Ë™œÚ¹…*ª(#+úZIËmCêx:Óô.ìíÏãgLÄ‘žÐ.Ô½‰Q”?;¨Ó{°‰ÜÙ°d:ª³—„R Çô®°Ý®ƒu}R6ko¯öÝ^\ºÄÏ‘²3ÏØ·±;å#/õšôüšY|“ ¡ öÆóÂçïdC³¿ ûNGªZ¬{¯ëv—C#¤˜ ÍÃÒU>=¾.Ë2úÉÀKöÒÑ!¯}a;-7òyrÙ! bqï÷ yí6¾m•y oK]¬Â´Z忪E;y30¥Œ™ùqRv?3n%`\E‰âœW2¸mCœáj¸>çµgýÉÔÖR¡{ïX8ÿ~vûC;ïݵ¿€lÅM\þ¨,)cAñ†S…k²¦‡Ù6¹>™)Y]©œï†BVxB—é°ŒlòœB‹gª`¦•çt0@‹QÁK­_;Ifüô0&U•å&"žeç q¿o(Ë0™Q»·XĽñ¿ ÄztJµŒñÐ"ûßHt~—ÓŒ[ó¾éõfsž€}!-´~ËSБ Ù';;M©šºQÞÙMYC|c·û 4«øð;œ®Ž+·øÁà÷¦hm>¿‘* 8é)$;0– ŠÚêC.™Ñ$M9|IFêŸ= ‡Æo¿C…s[ôˆ\?¤Qð†’¾³âçŽò§×Lb*`eœŒ c „åàç–®,,Q‘Yi³_sM¡×Çux :¼bˆÊÁ›¤“Úˆç\œE‡§ŸçVÕn©9ËúA/3rÙÔ唋å¡%ìÆ(GdÛßúfð6íóòÀÈ”D)ð"·)p-ªiÚìNª¦ìË,hÅ<iºì{ˆ†QU›)©8Tµ–Ò˜^(Ö®GÀ·öVµ›40æ¶ûzÎðä´“Üó[}©fëÖ$ÄFë1Œé!ƒ€74ꉌ}ÖŸ¶Ü@ǯúêfŒ4™RF*/ÂèB²Xݼþ)¥äíO`äcu“Æ»öN…>¥aÉÇ{ìkð¬Hqò]‘ÛŠ²/+9ÍÆÒ ulýÆi{­÷ÏëäÕFDnr‰öÎòR(ÊœµIïߎK¤i·óœ§1÷Ióåk©—k$ͤ2,G®‡pÀŒ£ê__¾#Ší¡wVÃOÂï:ƒ$ÙèR›:*¼@¸[bÂw9¹Ùáü¼lÕh×NþÓ¢±Æ$¸Ð«–”P(àý]“s3鯑;¿œ‘‘:Â.ÔÂGr–b~[¥Æ0ãm(¡.nöø§•ª"ë°¾[G®#.p̤—ù¯ÑŽÔNOn3½Åªn˜cˆ º§¨¸W&™`g§xL ú ëe{åÀvÁ©î¤.2‰4‘‹Å—Åé"]¸``y€5i…y8²=ùGÃl´¶gÉT Âê˜r¾8MuI”£"÷…ÝlˆÔ°ØSCгã£IM ÖŒ å þç6d±å÷­‡ŠÔWž©mêÁWW¸ö0¡3w?2¹4çIyìÔ˜[q¸FñÉ ¦ËUeóƒ^Å¿q¨¦¼BgS‚¾ãñçûñÆy¶[™{¤¦`gD“cBoéQR2þ|á<ÃÁŸiî,rÄ-`Ùï¿zƒ¢}Ù}x)|{íJ~Y ¸úH„oÛG¢-µ“ݽŸôö^N<Ç}/ÛøcHµbí­¿Æœ®eô:{æ, ™¾öx a»K¡En߸o) ZØ¥Gjá<)ÃòX@ ‘ºÛ:'a±ír¼ー2ÒãÖ!õ)ï¶ŒçºË2œxÚM„SQ¢™åµ÷©!¤9#LÀÜg J'òØ\Œ§)JËMÇMAl>¥ëhà•Ô, \r%Š'î.}>âƒV;Î>b;= <Íê×Yï:3¡Ð•ÂÎCƇ›%3ÓÜpꙆtÔ§B"ÒÜjÞIF¦ÃwÇ„;p1cj×µqÊ^w±Ò”a×ÊÐ ?R i›¿Øð£„zhÏ'9ýÀã* †!Í*Xâ<¾_Šþþyà/®($¢úütàö>lDˆÖ긿}ÒºÍbN9å™[_성ÎÜ>&™ÔÈž¸È —AN¯N£íÁc5$j°Ž}Sv2£/Xw\ËÍ8Z-<ÛñüžÍ€¡é`î6ý‘P’.ÓïõC¤ï;ŽÍ·ȟ‘ºžsoþT#¤5wÝR„J:Œ†›¸å{çÛÊ»(±2ûµÇåFîº?BPõ§n;eéYÔbÝÉÃ_(üýP5ÚÈ©_Ê·<ÙFLžVA*IÇ8ѵE_â'Ã7^åâpOóŠòlÆ1òñ¡î.cû ÄîŽi¿›¸µ‡!{ßg|«Àl:P ƒ}Ø}§üä÷€´‘^üž¬®fNPåñF¶/~§m¹•5ønó§0=sã @˜å'õºN»Bý˜nÉ;Tí_Í?0…² DýÌXUËl¤¡y)ì#òQAËÄÌo ÈRyŠø =†E‰ß}èé…Þ¦PºÖ H©õÌÜ4µ$g½ÔD/¸:Ç4{ÒoM óüÂ}ë•è&7¿,¸ D?øå*4ösŒ…óßËSqáéj¡š(d£…|x?­@{Mbã Ò¼*döM}ƒ Ïæô;/¦ªôVìŒôfü­ž€É<8S¨"ÆÌ“¥W¸L¤°Ù?y.%ôÓµÄçHBØoÁŽüƒöþâ¶d¤ÁǸ#,è;’| Q¨Í^!eÁöb¸Õ#=äÀ¨2jdé€Ïþg0^ ¬B‹ÏG§•dΤ4!-‡»M”gT\ù„ÏÁ]È™ø—"&Vô¡µ™‹– Ö´#G±Çú¼—qrêV£qÞŠ«ÄZäw@ 8¯¾»è\mrsí¨S†QZYÞØTc}V͇¼ß‘¬ÒÈä>åJ«ÜE2ÜG9œÚaå]ƒÆ~J‡ «#A!9Ÿ’õ᥿v–ÓN-?p࢑R!õÑÚ¬}“­Ù O<-­¹›ãÿŸ•wa -Š× ‹ÌÔ­ ^•Tqì5£H­éç7ª tpUùO L®J%eJØ¿S MÀfJÄ' Àª1ķϬSIAY_Þ1:DöÓUÿ¬¦]$>ÂÒQ®PÅåë –M3Ûæ+Ë¡hönà Ê­ŸËµÁ2¶yYó®xûíÁi4Óm*õN}bE«Š´†Íd”É¡`õ.*ü”Ä`ÐTç+E9RÝ”ª¼(/œ’%6§–[|¯!±ÝtToBºÐ4ht¡ðèG3f·‰ª/]·Ôõ ‘ž«r›mÉRé žÆÁe‹P> ÷(>ÿmL¹Í8Vžܘ-©{÷4~ƈ¯Ú# cqwoþz´Ón¯6‰§’„ÝcÙ¨Õ-YiíËŒ=Û¶&'Z Gl?Â[—£$Z†; ôUE¶-|ÓcÖcÃËü‚^Âfs±™òÂE2è’¯*{q)Hœ,/½`ßT.NA9x.a; +DµŠÜUK"Ë…<¿é“Ò?®4Êêíà0¶™÷“7‘1H€x/ݳOxÆâ_çô!ºŠÓÖ¾ÇÊÉ~÷ÛÝœkE:¾âÖ¦«DëBw­žóg‹¶éûË[ཚäïŒSxãèæ"¾à]æ]éeú%£Š$Š 6„; ?ׅꛪDÐo|wÞçx¡Ì묰fxYî‰_Ÿµ²¬¬L0(É›$^@‘ºÏ¯•ûêEÍ™5Ñ›4ŠAÌU…IßY\·MÀºcPnY ¶ 3PjˆU³DáM‹ŽÌbg­Ð‰i)Á=.»…rÈ»à|ûÊ$‚µëb3Ñ.GàÙŠÞ?B¥Eu§ƒ }%<=ÛµóI6ËçÊd¥¨­Àæ W¡ ß´Fþ½èüÏõ}V¨Tÿ“>•4H祩à“(Œ_”t½Š§*HlŸEýC÷ªŽŽg,à…r‡Ü W~ÅZö¼´,ó$ßãØ2´#ÄIöbÝöÁ[’iqXÒGäq yº†µÌýŠhrwŠ6óë!Ÿ2ÐÅò•î^ýÏ”¬Äq/m4sìP~ü48X—·³ZÒk Ãöëx‹¤8rX߇7e·1 QZË£Ij•¼ÞnŒ¨QÈÝl2ö3iò¿Õ'pò0×…ë8* êÃÄAöR3döö«%²\=¡w1}’[4$H*¶¡ÓÛ÷_± i4‚>¬ }ÉiˆWLeàÈg”,BðZ¥}$[¸¹ËƒqA¾³1ýå+`¹x SjÿT?öÓk‹´k7c šßbç#fu]”‚­Ï8ü%ÝH@©k¸57Äé›2è³4àîøí5ùÌ[Jq&×¶çòQƲ‚Á)cœŒ=¬9(CæcÿJžÀqÄž$t·¹\By tÇò·ç9Áð¨Kî±Ï墿 _JS C•*…Ï $:¢ ¯9ûÊÍÈKôYû´ÛóÜ2Ž ~…á}~-¸Õ¾|4´K@›Êf"ßjÿj°udá4ºˆ’8n)a݇ұãjlsåójòŽHJ¾ñÝ,ä,MZ¾¢îòs¶/Û˜ßw6í倌-˜=L(] DéaO×ãýÅùcØn zcÚ“ß„‚¤ý úñ’Õ\Vwª‰&9Ìd+§QÊKtÓÂs}븮ç‚6Ð;l^[œž»w{ˆM19–<¬?“ = ”lÕ§FØiSúZ Æ¦©+ἌOèÍ@iPK¿U¼[rºƒÇ‡¾³úxž^õpö¥2ü*)­e´Ywº h}és7ÁOD-42h½—:V¤ªü\ú¶_‰¥4ž¬¶w2e©?³ZäT6‘dU»{›XÏorßÇtcÖgÚ{5¢lèci§xÍ}I"\…=þ ¢ýÊ;ý›¾-Ðæ.eÞ io ËÑÒ™{¥µ•|ZhèE[vïwº‘l#q*\G^D ²E¦kƦºÔÿœ¿Î1dh`EÙL<ÈPH0ø%Å‘t'œÙ÷È= K`Keߎµ˜.qi²w¨“(QȆnn’Üûù«6œcS»ÿ¶ÌµxìÉ—üÏiN§¡Ð·×†¢¹En9ªó7Ú>-þ‚q¯2†ÂÏJQ‹fÓëMý]¤wHTƒ’HrÙ÷ø !îäÆÄü¤nðEŠ’ÆoGßN½úv× …mõ‹úg›tr©‘Ó¹>l)FöoO½'}5›‰ž©Ž9: §Œdv$$Ö¬4#;,ù©*DÈÆìf}*87Ú7úì!¨°ÕŒ|OÊDÚý*5ë5àÛ›„²­Èþ>Oãkç¤Hö¼=´¼$ºF}Cöy\Xagv"¡¡#“L_…öâwµÝ_ ß,f†ú}dµ%~‰)\î,õgöÈ|ô°ÔŸý ½Ý†ã¢âÛ°{—‰o¼J±yç!d/eÕ±ü‰Ûÿäq¨v˜5  Ønnõmœkt Äo¿ƒ‹{HaÈžl˜LÔõ8Æ´{$iåŽz£*èZ˜sê&“Ö°o@íS›<3‚¬ülK›~;Me»£=Ä&QMoká¾èìbêPó13&ˆ–wüàh5ôG?æ7è1£¥õÐFƒ"^[7̯v1¥\n–Ù![¥‘½Id9ؽA¤×pW‰fû¹ÂúâÚ`¾¸¶ éõ˜šÚ¯ 0ÈJç/G…¿øüÉó kjçsÂ"3>Â-k^.1S¯e~—e—¿óylVî§gl1äM‹±¾í˜˜hß$0›FÂ~~)QšDˆ 1‘b} ì}^[œ6õ²œÅª«G¿ø©n½æ³pî·#"4ÚÃȃÄ-÷µ´ØÑL~Í:U›÷Y5•Ú~ˆÇjO@­›¯šK#ßþ§µÂ+…«ñ½{·.1†w¸4œÎõôï€fr}³—3òÖ†Ïíªò ûį0¤®BX¹W‹¬éÖŒf4w‹ õ`[^¢Ui¨k¼I¨Ûî‰Øâ*ÕGÞå”®!=ŠZœóM!1bì|‡Å)ùläW·Y½Bùª’cv4Žéu|hGjÖõé›óÉ·Œª ­uÅih…ÅÄAS9L³îÂŒþÆGxu<£Ž¡b>ì¬îÉ%[í†3Ï/~–_ŸâúMXìºòÞëµ# –ž3ó _„’mŒÅÔqó@ÙÏØ*ïcª!Á R‡?¬[]WPî—¡b~Ùr~Ð)‰¿ù‡­XÂA?Ü#’/ʈ9¿E"·`½Kn†s‹«:² ¿BA²ƒ@­JÁ7ü¡$":lpÑ9¹Üfa»CŒT™TöÕryx¸%I·ûÍž¢þÐõŸ¥EÈËs0”·K4$-ó%‡÷»åõ†¦—°|Á„þr¢Z¬%Á”Ÿ·-iª˜Žâu°ºxÆéóyáb,dÔ-DTs1²&b ÒH¼%’?¯±Fm¶|ß°¡w<ÕÅ';ʱÔÌÀgoGùeRC>¹-¯²ŠËß³5s“DØñCJ_&Ôˆ22ãÈA£¯'×r°¨ŸååÉA›Åù-…¸t2´È“pÐïž9sÑ'TöLfë*Ø$løÌŸÒ%Ée˜ñ'j1‰ªö«‰9šÆnÉö°ð¤^4Fðoki*´AštîèŒ.Þ¨[É;‘×ù ‚4[,Œ¼nß1ãå âµµ£3Ü›«›¦Úf::¤nyW~*äp˜Â/µ…õxedálaþðÙyœ~*BB’µF°b' c;™©¨6èåðn‚…ætsŸüb#Çyêy!à špÛùíi3ÜŽÝÔ…™º“ëûG4  [WW<(µqí+ÉM«E?êQAå`~;“OÓ9è@NÒ©…™`\2 U&ËfSz*^§8Ѽ¨Õñ]*XÛLRn´¦e~>®gxì;õ ™Mi0ÙßÛj¬Q *Ýä^yÂ)‚oÔ© ´¢î´ET÷®Uò{¡0…ʾÁ4µÂ¡À³s®nƘ±”jξ3ƒê×ñ¶ÊM=0×#µ¤i”Óô/Ê1ÐQj9œŸÞl# ßf²EµÜ'=ÅIåuÙ¢F+øŠUž»‚k3'gܶ™ŒŸ®Ué×Vüc'X¨Ëâñc×ܽüåÕ\ÄjHí·~ÛÒÏ,Í0‘kÉŠøÐC&¯¾fÐÙÉ$`ŒîmAÈ¡Ïäë0ö 7þêý Mûkö"žX($`â'Y´«O4}à¸CrùJ˜OÜ}⹫kš•#3õ”׈Dp ázOEàÑŽŒ¦2˜†ÐÏø}šïñï¬E„7{…EkXr Ê¼|z2¤RçN]ì°õ×É|¡fÃn©³TÛŠÂY¤4ÉòŠ%ñ“Çܺº£ô5‹ö¿.gÖ¯ìs[J|Û¿v³ºÐI=¥I]™¢òm,nΊ/='etZ§NÉÁVO.Êä +Rµ%Ø%¼¾Äï_d”†â~`¾5Vh‘ÿ]—œ×á¢(iÅqð‘atüÁ†„®R•y;ÄÞÈá¦Y‚ ­B˜\’³²b£=1´‘ãì‰G˜®pò 2`©ÄÄ.cey8ÿ]¦TÍw\@NC `ËkT‘¥o³9 ¾ù¸³9 NývyUTeJHIÁ¹éH*“9:ÞwbÙ>U¸È¯¸ý¡cˆÖX8Îa=rÇ:ƒ0Ñ“«S5:<_ûœší‡ðvwna „.æxkõoâQ÷…Õ¨÷1½La¶þƒ ÝXqÇùiÍÊÍÀe×ÔAnµOd&öjFÏÝdl÷éMqxxågÈ–]Ñuaû1¥¹ÌJI>½É~¼‚¤Ã(©™ /^æû ¼¢;˦æÉT1p'›f».V¨Ì+Ø­›`ˆ ÇÎÊníîpuÄ-.W}ÉdÛÿYnžÕsX®KUl#dy·÷E‰$áé<ƒï’ßåh7&0¿‰0õEôËËŠ'&õ(q¶þŽé5ÁÃňj0oŠ¿ª©`¼®žÙUµÚ›áI3*“š'ù‡×xx•V½ý ‡rm8y’~Ga-ÜlìóM(‘š˜&W$ü d»@®¬+)>{ýêÛ)ôFó swÊ‚5 rq®:ƒ¾LóÁ¸Z‹Z•‰Žûá)D+Í^ ûÊn4óz]ÎG"É@Û Êº‚à#ÎEø³m'LDA›Î°w-Žú9Ó%ÂÎÌY¬juI>üÑÆK'µÇ_½ æêøµ Ïä;Ñ= k¿kðõ>×ßs —HøSÜÄê_òîûÖ£N†éȵÚÒªã9|Ó‹ül¡ñzX›bå³ S+ºËXQŠ×SëRÌÿbRéËîZŸx±+Äò°ž$ü2’#Yº²Ëø²> endobj 16 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /ZDQULK+CMTT12 /ItalicAngle 0 /StemV 65 /XHeight 431 /FontBBox [-1 -234 524 695] /Flags 4 /CharSet (/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/seven/eight/nine/colon/semicolon/less/equal/greater/at/A/C/D/E/F/G/M/N/O/P/Q/R/S/T/U/W/bracketleft/backslash/bracketright/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/braceright) /FontFile 17 0 R >> endobj 102 0 obj [515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 0 0 0 515 515 515 515 515 515 515 515 0 515 515 0 515 515 515 515 515 0 0 0 0 0 515 515 515 515 515 515 515 515 515 0 515 0 0 0 515 515 515 0 515 0 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 515 0 515 ] endobj 101 0 obj << /Type /Encoding /Differences [ 0 /.notdef 34/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three 52/.notdef 55/seven/eight/nine/colon/semicolon/less/equal/greater 63/.notdef 64/at/A 66/.notdef 67/C/D/E/F/G 72/.notdef 77/M/N/O/P/Q/R/S/T/U 86/.notdef 87/W 88/.notdef 91/bracketleft/backslash/bracketright 94/.notdef 95/underscore 96/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft 124/.notdef 125/braceright 126/.notdef] >> endobj 14 0 obj << /Length1 1452 /Length2 8114 /Length3 532 /Length 8971 /Filter /FlateDecode >> stream xÚí”e\Ô]÷î))én†.‰¡Cºi ‰aÈ¡‘F$FRº;éî$¥‘N%¥áÌ}?ÿçÖóg~oæ»öÚëºöÚÁD§¥Ã)mµ+@Ü9\@Q€¬ºŒ!äâÁdb’u[¸ÛAä,ÜÁ¢ ˆ íaàåEùøEø1™²PgW;«,Û_IBiG°«È  nán v„×Y@:PØÝ‡ ´ÿšáл]=ÁV\˜@ ÀÊä°ÛØ9arÿåHÙÉ úWØÊÃùßCž`W7¸)+Ü$nÑ êñX­1¹5 p-0ÜÉÿ SÿY\ÁѰpü«üß]ú¯q G;ˆÏÿd@=ÜÁ®u¨ØÕé?S Àÿ2'…ü—Œ²»Ä$ídxþ²sS°ó[iÙ¹ƒlÖ7ðßq°“ÕZ€·íoÜÒZzúÚJÿ³ŸjYØ9¹ëú8ÿSö¯ì¿ø›áÝqµóópñðá‰ðïßÿLÿCLÞ µ²s‚A€…««…&üdÀIàØ9Y½`o¸cn.'¨;| Þ’€5Ôó¯íäpÛú8Û‚þŠÿ+$àv†oÔêwHÀ uÿÃ<nw/èoÂÙÖüG/€Ûêáú;ÀØyþ‘Áàvƒ/ò†;q{þaD>ÅÅìö×éÿ„§Iÿ&¸W™ß$à–ýMpÓòÿܲÂo‚—VþMð*j¿ ^Eý7 ¸5~¼¦æ?$ _¤öo‚×ÔùMðåéþ&¸‚þo‚+üCðkÁmñ›àz–¿ ®ú‡€<ðEXýð¶ƒÿÀ¿zþÂýØüðÆÙýpGö \òÂu#®ëôÂu¡ \×ùükÛþ@x#\ÿÀ¿¶ù„Ûpÿá½ðøá®<ÿ@¸+¯ß¹½ÿ@¸+Ÿ¿ñ¿¯£Œ ÔÛ~9yágnQ $Àð¿%‚<\]ÁNî¿tðKýo¶¶ƒ?`°7„¹0 ‰…Ú§4„—¾–ÏŸ({ÂŽ(cÓÓ¨íúÚþ4dþ="¤hXÕ…}å“áMy!Îö“mZ¯;J·¨6ÿ£ ?ƒ\`f¶=Í·Ó|›) OÓÔ}¶œé/Cp[¦Ï5§VFJ_ôgäj±Êéî }£Cè6ö¬ëN2THƒèE„}bæ£ÓÆûàRɱ셗²<òÚ>½‰céÚæAp“ž“ð`†l5ªo~©ú#Ù{Ãèöå’ æiIÔ†GŽzêËØÊ;Kão´@cÈitú4ËÙ3w“ÔªçŪ鬣kMtrþ2Å·*BØvQ-ítz5°ÌãËym¶æF¿h¾äÏRÙª*>ÖGúŠ­Õ}ʼnmé|Àb2“à|dMgc|TáS [ˆ› “¿¯¬ L¥qƒÕàìÚ+~Œ´î£×bœÙ çT^©Ÿ?IZ éÇ·-€¹Èéã?ß0ÇÇrèª-“OÀÓ€?jÑ*ŠWs¯ÕNýƒ~5œU(ÇÊ R^¯Ñ~Ôc¹ØøâƒÍj£*ÁÌ•@æ¥4Ñ3e44ˆz»Ã ´Îª-¯a—Á:^Dˆç¨/1 ¸¬piršjÄ>•EÕä§ \’`öêNôÔ¨4ì;Ï:A—}@ÂÍ^]@ˆ±ÆÞzš>—WâšÚ̲ž £lÖß@•ÍMOJ~M±é’ÍóôÁÐúxvñUÿ+R Ưh?󙦅¬öÒ‡jðb‚LN+*o  ]ž0S›ç{QqfÁÙyÌåÇ~þ8_°yú‰bJnø•ø‰îK6¾eA³$~¤áçè~F7+QLfì ®½Œ¦‹[ôÆg~ºVus¦%{0Rùº¸ˆbÖsÝ8Yð² FxqZ×w‚ƒFßâp¹6¸ „Ò0ðù{ì°9Ó$Ìtt°¾j$¹òb\“n ;?JüÇ-TrÀ"stHQÔ‘’c‹ˆó /¬9.÷Ë+«©Êæ mE6—ÐÐyòË¿ÊÄ‚™ö*bxªyg}Y**ÃD4Š.ñÌDŠ¿³±Ú;(Øä(9ËŠÂp©{Kw£˜ym¢MéäËx²»X>íoÔgõB²bQÕ7šÁ­|¶Œ¹B»|æéO®‘¾Ù[sm9‹W¸¡LC&Yå~îûkäí:¨ÂƒüáûúU$Vó»¢épÕ(î5û™À£ØÛó´GÉdÏDïÏȃï-/QßÖû¢üŽšÙ•6dÎv…@=`Lô%ÏÑ+‘/¯d³Ì…k/™Î‹žž£v›B Ü¢ªÊÆmlŠBïrX\g4‘k¾V6ÐP]2yØ)ØM‡Ë«˜6<öÛÑÉw¹œ$Ô×PܳT§f¼+éOb¶=‹ §4¼n¯×ß=ÈnÊ»¢Þ­'X›2á|*ZæˆÐóš’£¼' üþ‘ Åm;‚+ýžAu€Žå—hÀ"?«2ÊîZó¤€s]âh˜]óòq‰]²ÑóR„%¨}Ïö‰¥ë¹‡©`pæüœ+â“3ÒÅ>ÐCvw~ Ux-ét#²%3‡ÌP½´™¤Á Õ:ÐMÞ4óuìÔÔ¡áýè”pÆ6Ž@æUÊMÐ…ª\ŽTå=ÄöRÆóy«tzιØ~+;`ѪŒâ™' .ÄÆŸ·úÝ€"ŠT}BÔkMºˆ-e’%¡K½æë†¦sžV>¶c׌w¹üRüWº"uªÉ]cäÒá·#žS½M‰~Ó9Cà Œ’vâZx4udã-À9”ÛÓ•aHv,1AÅGå¤"иÖjZrQsz£ 6pãaNI îÁt DÇ”gö'—•Ñפ,@)JŸgöÃŪ;‰úâ6µ¸ž«gžNâ+µÖs~›Ž+ÆÇè6v0½ñÚðÍK—Ûxš€P^Ó ê ‰lrÑÓŽZ JÇJìoJý&è¿džÖý¼éó¼–y®¢.Ž¥ƒÿ 5Ä=œ1¥µoUªñŽ8$´í9c JoR¡Ô|©„ëDkå?ý©´np]È½ÔæôAòvÓ«Ði,½ÇÂÆˆÉË cž/â[nDN{Æf5#Ä~žK{}ì 4 јšE—ý!˜5ã1QÜôZ“Qñùzú×J‘ÅÔt;rê7hž×¯·²éñéï<Ûž|ÕoΦۤ)ÌÙÓòyþ6šœëÔ’MŠ;ƒ†ÈéÕ¼³skÐ"ªÆYSÎ66ÖZ®¾ªßN”ôz ±¯©Æ%}­€‚o˜[ë|eÒëž/õ"&cúŽ¡ŒD§JkB|ï~Õ§╵º,œèÝOÆ»Ï:(óMEÞ§m!dU€÷Üs¶N$£¢íð5Ñ„Nò8Õž›1 Möa R,“àÇW 2]ZyR‘3—Q„E¾ûE½à%;ú‰_Gÿg}‡#«„!û¤èbÍR„kÑêó/„÷o7š·È ô ÎöH¾¬Yé «LE§&î²gGG¼4GÚÙhôYjÁ·è‘ª{{àyx‡²Œšâþ * K{³ÃÀíqÛÖ#CyÛ3p@Ý@çˆ:qu¯úyMlŸ&6.î'Ryî†gÄrØ×>ÂÍ;®4å'e5,’tß‚’võˆ»1q UŸA®vóEÌ’ÓÃ\&²1¾ô¼GåìQù5Òˆz¤Îïr‚o.½*¶„íµ¡â÷dçuÇg¬{ÉÔÕfô~,ò²Ü•ÝÚ¥$×2p›S  ”¨Ûèÿ±Øw=X™èXKF~ÊDG B4ŠÑ°ÙÇÝñˆ§í͑Ў‚ö(ÃÍ`Ïòâ“øl’fv´›Wãò†[Ážˆâ¦’)Îȸn›û\vÃÍl9Û}«©ÃÄßtîÃj6%Mü:¢Ê:%ÔgÎ|~…œ/žú”Ù  ®2²ùq˃ý.¾º,ÑT_ßÞõÁ²p5!}G[äñ8°™D¢’nµ.þË•gä‡/á¿,ï[í&ã푢ȴ"´K»/îù—xpGe¢¶•Ì)L?àÓwÝÙ ŒŽ¾µj˜â œ¥='/Ujøêuº6M:Ø£Ö`}]7!”EM»ÀŽ"¿CE¤°9cÉç™Yë}ÏK½©’‰ËFx™I¶Þz¹UúÒÅ€:b¾nx&sŸÇ©¡A™e(C§åˆØ¤¼Zë*[èQÐË_|³®ÀdAó=T¥YªsÇA¿Ïº¡î®{zàéÚä³±»b¸ï½LE:;WÛX\ë²¹™» —¡£R´‚‚Îýœ×–w¤6ºÖ¾bŸ "üjÑÇTR¨[jÓÊzâÂïd—]†ÍZ§_uã‘ ¹ðÞ®`Ÿ±2EîußCtûúršxå·Â&ŠûÓ…iy]Jôà„ñ+Û;‰upt{LdŽCœ$•z”p†Qz±'ûþ«3R¨.¸á;î;9wÚ· (Šäë­14Ðu~šWɉ"¢oÛÙA*¢ç¤&JŒþö™ïT•¥²×ÇôWÔƒžåI|Ÿª‘L—ë‰^uúø•6¶ Ý·‘;ˆr„Á"[Y)b*ïñŒ,xj&ñ@sß>ÃR¢Ós•ûEö™$½~ÞdÆ_[ûVnbÝ­\’aÐçñiëÄpª~êùãƒnZÐðôÛVOGÜ:ÊmמÊ'‹õØöAå…sHÞ°ô€ôGÒ˜ S+kì^LŒi)?eÊõÃç4°ôê™aB6“iÉQÃHKöZ,]㨯è}›:›I÷ÖjÚ³|·½U´£®¡ËË G¼°$º“8‰ûáú¾ù¾gCʽ#'m}ͪ>4‹rŸ™Ï9>…¤ Î÷* !ØL¦ÇÇšù 0]Ä_+"Gk¹¡ƒ¡ÄØ\§¦¼ÄÆŠ~¶JÒâ6Xw#©Ðý£lŠ“G¨¬æè¥Á±‚;åc Ñr«k ré—ÌUÀ•Êè¡s5aû‘ÏÛšQž\÷•JÔc* V=ö-#q¨Hc|ÜóÀÕ KÆ‘@°¹‚âÆçç/ÖJ5€·Š2Éæl™×6Xµ”À‰ úoÎÏÒ«ÉõåfK’7Æ çõÞì?å½Ç¾ÿ…þÑ*Ε2Ù=ÄTèÅ-é/¿{ê]‰0ïgž«fߌcÓ(HOw¸ÂbkÓ'&{£ð„€õÃ~(¦ÙO¥;¿—/«)9–| _`Ú‘6X懬à]˜@b`ÏBeпaDWÖµnV=pY~\)]˜gÑ'6¼þ¨”Ô6W©â¨å¦ã[ÿ©)µŠ{·µ&³ð:JL¦ ûÒÚÛEõY„QëKv=Qf4[¤œÉ¹~ ï^ïóI B§Ëº7ËóS : ˜9ÏþƒŸê³OYÕR†D<­/¯aSŸp²ÒzÒ ¾ ª¤ò˜zÊY¢×´9[,¼ò ãÞ(Ï—ËYé¢Cµ4ÆUy¯nSCõÓÖ;dο°Ì~,»2J?½)òK‘•âh¡þÁd®ªtôƳ™*D–*Æ O—·ÅÿÁRêcPÛnŽ—]4’¡SÄf–Zò{ùØ¥éZ™ïˆ#Ü`‹í£’Ø&à {H:ÆSÁÚ¯ôŸ›?­ž›3ê#È‹Þ+Ú´'â·ßöûëæS½bh¿] ˆ¿Ä}.ȃFޱÍÙÕÌäuÉ‘ªM·Ká}OnòÛ›eCó@­oùküRpÏí™Lû°”®™ÁЇúJ#u'4'ɾ=ÔÔ÷#Ñ¢x|‹‹vvO#2y4ïŸkºi ’7 Ïû>¶Î¯œ ƒõ'àgo|ÒhÓqÊ.(¹OrÇ<•ÎÐO¼–[,+§,ØOvÿD : ¾à67G‡i?’˜'VÓ ËH3[)å¿y+ììÚµ8á„©ØžÕßòQîM뾉”Ñý„¡–ÚŒŸÆÏç­'ŽB8Bf¨Ž ûç²-qI~€ºÅ¯tmŽ)âxäÔiîZÚ§sAdÂ÷g3Ô”€9Æb®=ÏŠþ wÚ‡+ÀMèuóG¶±â •†LŒøÈ5çÍWñ ,’Ë(y?€Í\ ‹_ñ³RϘLÍóÖÏA”CÝV›¢óýÉ=Í+NIMÊ#¼¸œùU²±ÞVG'ÃBßÓ8IF$ørźéI.P©”rÍ>«¬ðÿÒE;¬\«êÉûð¶z6ŠÕðY-Ÿ q'9[C®ÔcôÄ|>“yÍèSÖÈZß›ü²U_µe›ÌõË'©å­+Ü´EüŽèƒl­gÜÅ(Åu¾BCíï°=p€zTº(Ÿñú< 3äÞ}'Ä€)ÜÃÚ_x[ÈâémL _X\Q^Hk¶K臷Í0¢byú½äŒ]y÷ù#kSiJ²òc¤)ÃFÞ"ºÍãÀô|ÆÖ…¿ÊN‡‡Ÿ#5ä„Z±CkÈÁ›Š£ñM} òÞ+ÅP7„¶£Pq’ìÙ|8Å8Ríþàû½fUyZwìøvÑùá–),Y¡¾ÿ"‹ÕC¤Hº@Þ0°“„_{÷rûXôçuZBz;MôU lì…£C,gõì¿;Ró©¼Ûpñ£–umÚÝg纄E¼š=®§‡ÂT‡¸½Íþ~>zúv劳ˆ˃oc ]kµvû·›òã:ó ½-õê‹ ½•bÙJ¯ßÑáó+š5"zº¢ê«£“FHg!\é4T!œ†Ø+'¿á÷‘Tqa¬LäçSÔuõ ]fd ”(ç¹¥ù³ésÅìæØ×yÙÒo ézX±—:h6Šæó¨Â6žç£Rë5®¯í‘°¶.cýÜ#ûT[ðRŽ<06)±KìE@,Áù{‘¯ÝkçOA° CÎucM’l@ °jXÂ׬.áÙÜöijŸv•wä>Ù~9Ô³6N±³gë<šJÇÞ…âóéÒw*£šb b®£7F7¬ŸIrK[mS›°¿ã÷J¸=ÞdSJÊÖ»"Ï=ÆTÑ«á&¼˜‚Ô! ßÉ›ïK<Öå'Ö»ùÉyD¿ð½óm»i(ʼnÍx2•犜ñtQ]{f«—ªä~RŽ~L$ºúƵ²{ søMx.iĺ{yBU¾ýpÐG•ÇD¤b~Å¥Ofe2¼XR¢vm‹Uꇧ¢“oùÅ7Ë"ÆƬÎ[©ùK‘q±Ü—`tõ¤&’© <©º¦ÀÌm¤Ë$”Ü/Üè½üëæŠÓ7b:>Ss¶úÑ׺§2,¸hü›öãš# qsn ç¦õø õg²ÔOï2 a•½>¬+Zy¾™‡,Â6æ»QاÉS öå´/vmøo“ì…a÷Z¦ÞïEâè3§ã±biö âê-o‘A~¦æSjì9*Žthï8SM)!þéj·ë';($õ7Áµ9úŸ»­ä‘%Q&u«³‡£>Ùª6…Y%{Ñ/rÈ@\Û!8Rµµ–}N²òWm±ôÛU¯ºiH½*´?Ö*W™ü$jÃÖExëÐquÏÆ«¹Û?À$¿–ø(<¤=3'ŒRAÈÞaTº¯vqÍþ %Ð(XÜôæª.Þúºäç äÁ)¯#æ“ÍÞ„íå“á${P>r˜t;:L@éàXvÑœ%9ï‘›f*œ[7FP³éÛÞ¥®L–ò$ÚÃÍý;Ïrœ)ü-¯]ÁÀÀÏFãÂÏ‹-Ä‘Bµ‡!øI§ÏÏ‹ìñM5-†pÆ}—iìAVøÁkaÅÓ/Pî:_ÞnÇÕT³-šöæ41Sƒ2p73wtö ¦B8WyÜ8žT)ýßìk’Ùï$åÛÖß(Všmîé¡ä^t%ÛCÕúµ«†v¹åž&78júŸZZͽwÅY=sâ==Œ=ÇmW©;òÐÉ•Éó}x¿Wn³P%^?2(7¨À]œ4Yâõ.Í‹Ø1/azEï“ÆBº©¨ªåæt{’W_I¦]ìÀ>Š ¦a¤x–>+‹”ÉÂó£z›“Ç™“\艧4–¸áRîcröv&µ™Ö§Å* Aèö L­ÖUÒ«2zƒ_öÒ-!¬Ÿ\%±ÿT¼\Ü×¥sÝ-Ìh™òTém[Uª1¾Ð{;ÖFÐTÃ×›¹ZëRåËZ“Žl”Äv»zu½…Ýæ[Ó…3‘\ÿÄ4JÏ©õõ¥2ö2® ÿC|¤qöXû¡†VõðµYö»ZÇÛkl’Waú‡óiQùé ;ùZ?<0ã·¯i q2m'°eÛæ‰#€äÃÕ+1jïÇÆN%Ø‚°Â)z¾Õ‡üR[^¤‘»4ðER®í³gŒŒFÐÑsNöÓF3ѺëÀ¾¥La,~ ^?‚IÌ›O_y0Õú„HO™2/È"„Üýòîš@fg¿õ{ýzi¾ölj äy(6ˆèGú©CîÔ÷sÛŒ¢3î@:ÄÝÔ÷nà]p#osò‡ÚÙýÁkT@U”¹ µ(öyf—Àn™êÍ–—ÃOÖ(QÉË[Ÿjöì£Îy­ö^ùXi'Ò?ÓòíLÔÆ›ÑI4õÞßâ¢X퉬ùcõjR §(g%ªIwˆ?Ī&Z´µD…»kVÒuŒŠWè_ºcx†UûÀš°Ù®w«™­Õ‚V³í¿‰ìì@_œ ¬%–Ž OóÉÝì;."å·HI?>Ô`Ƈ¾(g¿8îüì˵OÀ/õðè²9¨åYw×|£DU©6Šºƒðáÿõìì`BOÚÖ çœr»âãµyƒî³ ‹¾O3ÄšŽ 6ÅÛŠ[?ŠÛtØoòó jOÌô¶•td;Ì4ßÛôzR®-ùãÜ‹ =_þnÝnØŠûìbnRß+¢Õ¢ZJGoÄ?*Y;ŒH2ÆéË }e¯?+äQ°Œ’Ú&«4€eq!ð ‘MĨ¨Â £åBrt)M¸¨kbÐ<_n"Eÿέ´(‹!ÖI?Ø”éy5H¼ß+¸!Íç8Ç™¥ƒ[½JÖ)cqÁ—;=„5Uß-XúOòÉ$•'ñs$î.²Ý§®$Ù*7ö†´™6ßýcúw±2· ¬"úzú²Y€>„ÇXŽ&ÞåóÈÇáOå'=ÁÙGµ†·tk–hŽ[ñ€¿òû®í ”M…rG8Å¿ýŽè8Dú‹-Ÿ0w(úÔðN‘’%½ß.¿ž!ggpk.Rbß ’T$µ(Κ®´u6ê¾C-Ë=ùÁ5Ä:FüTÎ;®¼ó²Õã1»q,Àãº9H æóQ"ömå>1À¥H@zÕx5í[’*ªï¾?ú\ º‚”ÏcÎÖ% ›zYèwÝ™`khCn/]¤iÁVBÕ‡"ÅH¥þºY8Û£Í íó‚Èâg.i}Ž]‡g‚\.È)CÉÌ—C_ôëõ)€rþûüŠÛïm˜ã>dì”4ÚD؋鹓 =¯ ˜®wcIóìÔ#Rv¤¦ý7e8g8 YÌ\ÚôE|ðµä`oÔÉ€q¿vŸ!”íóõ•‹&.”woHØ›ð=U!¢n}A¾T“­rˆ6þ:è¢qÛÆÐãs–Ù¡§%ÇF”Ÿ¶È/ rFNÂðW>yv±ñ*íâòõp·þIÜLÛq! ´QÎ9žÿÃæÿ/ðÿDláêu´puÀü_];çÀendstream endobj 15 0 obj << /Type /Font /Subtype /Type1 /Encoding 103 0 R /FirstChar 45 /LastChar 121 /Widths 104 0 R /BaseFont /APUVRH+CMBX12 /FontDescriptor 13 0 R >> endobj 13 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /APUVRH+CMBX12 /ItalicAngle 0 /StemV 109 /XHeight 444 /FontBBox [-53 -251 1139 750] /Flags 4 /CharSet (/hyphen/period/one/two/three/four/five/six/seven/question/A/B/C/E/F/I/L/M/N/O/R/S/T/V/W/a/b/c/d/e/f/g/i/j/l/m/n/o/p/q/r/s/t/u/v/w/x/y) /FontFile 14 0 R >> endobj 104 0 obj [375 313 0 0 563 563 563 563 563 563 563 0 0 0 0 0 0 0 531 0 850 800 813 0 738 707 0 0 419 0 0 676 1067 880 845 0 0 839 625 782 0 850 1162 0 0 0 0 0 0 0 0 0 547 625 500 625 513 344 563 0 313 344 0 313 938 625 563 625 594 459 444 438 625 594 813 594 594 ] endobj 103 0 obj << /Type /Encoding /Differences [ 0 /.notdef 45/hyphen/period 47/.notdef 49/one/two/three/four/five/six/seven 56/.notdef 63/question 64/.notdef 65/A/B/C 68/.notdef 69/E/F 71/.notdef 73/I 74/.notdef 76/L/M/N/O 80/.notdef 82/R/S/T 85/.notdef 86/V/W 88/.notdef 97/a/b/c/d/e/f/g 104/.notdef 105/i/j 107/.notdef 108/l/m/n/o/p/q/r/s/t/u/v/w/x/y 122/.notdef] >> endobj 11 0 obj << /Length1 1854 /Length2 12203 /Length3 532 /Length 13230 /Filter /FlateDecode >> stream xÚíµU\œÏ¶ »·@wwwwwoÜÝ=¸{p Np‚»»»$8A‚»Mÿ÷™³“³çòû®æ7Ý7ý¬ªw­§VÕ[MþII•^ØÌÁ(á`ïJÏÌÀÌ•Waf030!“‹:]­ìÅŒ]<fnnf€°›€… ÀÌÁÃÊÅÃÄŽ@upôr¶²°tP‰Rÿ3‰ lt¶25¶È»Zí@9Lmª¦V@W/€°­-@åŸ'\*@ ³;ÐŒ™`feê 0ZXÙ#0þ#$moîàü¯°™›ã¹]@R*$5¤hæ`oë0š#0*8€jA&ÿHýgr 7[[c»ÒÿÓ¤ÿcØØÎÊÖëOp°sts:äÌ€Îöÿ9Uø_nò@3+7»ÿ•v5¶µ2¶·°˜þ+då"aå 4S²r5µ˜ÛºÿÚ›ý§¨oÿR`ÔÕÖT¢ý¯ýüט’±•½«š—㿳þ3ù_Ìü‡AÝq¶òè21011ƒ&‚¾ÿýKÿ?j‰Û›:˜YÙƒ;ÀØÙÙØ t2@ÄðaXÙ›=@O0#ƒ½ƒ+è¨'~sg„¶´ãŒæÿŠý²€Ð겂ÐößÈÊ `trsµô_ûï0€ÑÑØho 4ÿ+Êü¿£ÿ1”ÒÑÖÍåO€ Àhê`ggü'Â`´ôr´Úÿ q€ž•u0ûâ0ºØ»Xþ‰p½Î _{à¿™$êêñgœ¤èjé ükÆ?ëwpsþø§VîÍ麀öæß ’uºÿå ÚFàÿX3;HÕÞêo®Ölëð×CÜÿ¤±³úŸQ ÐÉÍøÏp€Ê ÿ!P)‘?*#ú‡@5Äþ(¿ø¿‰Ô‰?ª"ù‡@-úC õKÿ!P=¹?ª'ÿ‡@õþ¨žâ¿‰ TOé*¨ü!PÕ?j¯Ú­Výªkü!PuÍ?ª®õoÝ4ŒÎ7hÌäÌLÿœp&šÙ_øOÇÿÂÎÃ_rµø A²–!Èö¯w‡ ¤ký‚œlþB”í_²²ûƒÌ +û¿dåð‚¬ÿB•Ó_²rþ ÿ9 !ÈÊõ/Y¹ý… +÷¿dåñ×å²òü AV^!ÈÊû/Y®Æÿ~AÿÏRDÄÁÓ‡ž• @Ïz¹A;ÈÉÎä÷?智9ƒ.×ýù€rý7›[.e Ðhаºä`Êjþ=¬Ü_¼h¦š\Ä¢9A¡¡g¾1d%ܶdLÖ‰f«^ë©2åú€Øã…À%ªÃWyRâ<È)!cñíÀÝè Ó»•@ë*SÞkß‘ä>äµýûÂÍ);¸âÜÖxyŠö×Áœ‹¡“%*1µCØO`½ºî½Y¡œZ™¶êáŸë)X?© e8•G°…oz ¥$AmN‡ø[‡ÃµÐ®_:t¸¡?Áå'¿éÝüšÒÅÎ^äзŸZ\¶\²³µ4ŽŽ‘¢e#Ž)ŠËjm{yú–Í(8Ãú"!Ã~?;Ù˜C¼…4iqlß·1ÇŸ!xcáóx¾œ CýAiŽËž‚v/ p­=ëžîJcÓ¾Iá´M+¼r•µÉ÷¨(Ö†JyYZÑÞî–wüý!­)üGš(³Ÿ¡1Ò*\|†4ºéæO¦ûzÍ/ÐzѲ«³¿`E l+M¾Ð™Ÿ%4NÀÓTÀÆl›H°ê̳¬•+ÍA¦–rɱ¾;áëFºÛ›ŠôX~ó?²àއ ªõm•§~‡÷Ó~ÿb<›Z.µ»âËL””Zl÷)\W8#Þ»@ËQ©˜@AT½óJ}©žs*íJÍâµ õ³§áM‚eJö„×ÕCµæâ}Vëà´Á™~†fkš_VÚä´Ëâ’á½ÎS»¹‹nÛŽ™¶3`$oÖÅ‹Â]&bƳñ…'&<~ öwáf^uÄ ÿô¹¬Ó&[êÇ vË2¹QR§ÒH|4|6G¥×’ÓûA‹9ŒH¾’2 ªaöÙV,má¥aǵàÉ‘òXðDÞLg) õj‘»o;†7;îý¬YÌßÛk=EQ¬áÛ9ý˜Œ ‰ZÃÓZŒüO;¬RÄËÌûã ÏüÖÇð(hî¾[ÔLws0Š>} ’›Ìˆr1½ïk6¨Ñbª•–@A¦eõЏTjÅeÈÈõP$(ã¿vÿ,%6{ãê!(h-à[\yti ‘¹)“¿¥H¥iÞc_¦mš•419v›EHÛ²1æ&®Ù}o£š!“ì˜\qî–ÃR˜)‡ýlŒäg!E'µüx$Œ„ öÍÞMã;¤:Ûaô¬Â•BðÛ…,µA™"—àË›øÈ»«ýñé2.YÔ€§ùÁl]1•Ț¢TµY2+¢Æsµ¸xøÃ]ìy^š@NúgÉdÑW¡ÑÔAá³q Kèoê"Ãk¿øwA2²t~¶‚Iê–Ȱ•ÝH`0,öÚ ÑY×%¶ÝîÜÌ>M®šˆºûJk9XÝq†¤­ûªª'·p@ß@ÆŠ„ˆŒˆüVˆf†5æD\ÍÀ+ÏD†JÝ"g·´AFøQÚeåaN¡ùèñf‘ÏÉPx*‰°äßaèÙ5ç#O_çHbmk~"© ûµ¾øna©iÚ.*ó€ÏUébù¸mŠÀ‰'½»GpËçÇ~Põ W”wÒÞ‡6‰È¦R;]ž9^`c[zãêó QùyÇø**A©]×Oyèq÷j¨oJ46A‹qàéu“¶é4SÅJüÓ/ŽŸs¡fì±@"Žz…[Ï€kÃÕ^Œ±Õ†_ì“a<Òw(:ÍëÓé\V $/åÉ~Q2Ó­°œ!¾òe—Ћùeö ‰)!Ò½µ=]7á…w^h‘Ã<‡Æ¤YÄW$u:éBÙ‹_òZŽ¿T_®o¿w8°hܧ¨{ÞL ú hK±¡)lH=r 온 ss}“ÿø!l»‹¯ ËܰqÒÑ ø¶xy+¿i ñT´¶èW"´Ó3¼4ïù¨}ˆó*ö€d šÕh¾óüÀõ U7¥óEÔÌ?ŒŒ´¯ÔX[Auqxήã\‚¬¸é¿ àì9*ÄüË[á®.ˆ9Žõ˜’ªäû]}W.9!|<ËàîöZŽÿÅ¢6ì÷‰¦Î ±}ÜSŽ¥¼¾£Ù6%šÜwZ¶EÆñ×øúÛ£¡äœÝë¹’âSTÇÎz•¢#®õÄø–¾i±A_™tšú±7¬¥£7n#y)¥1Ò‹¦©'Ô“Ýï*õ«Há8,¹¦½ðêáäëuOR u&8/”G†/Áé©?N·êåâ¯Èíàö†çŠÅc²ƒDF𴛨©á|eÙÙsŒôê ÝÎuŠ_Ñpq"Ê;̳ÒfŠ;~TÕÌà*´0c*Å™Cm¬Q ô7ΣA²z+jÜYÔ‚ù™2͈ßà=i†öIWqÔB \õ{úÃd<^ÎW•‰w¤ FÅEù†šÍ@×Dûú²íˆ>ltï–m¯ßFN*×=©x§Ä„Êðù½ý¶wIÎ|Pɾà†Q$FJz‘Œ,ËkiøÙzÞߪ²É2©’jÒB+Ž`b膢ßÖÛÑJ7úó—Nèüºù´  ìäù ÕO4ÌuUí#å“÷$’mUÕéš d`ÕŽš{®ÃñÝ ;¿- 6~ä1Uoiþ}c‰6ž7©î=Àç…÷md>¶Ñè`]v°#“]¯ç×¾´ž)W\xB°dĸk.\í{O® UÙ¾)Ñð^SYó;ΜŸñªÊ«’¾Saÿðñ×m.;ܵíñ —ø°x¸4Âdü@š’w°%«Úžq+Ûwy€Fâ¶©OíòÀM#%XÑ‹…AJ…¼IAž¦É¬ñ\e¦¾¸..0 ‚ï7qvÝâ ì5@t ‚ôy§+¦¶ª';aÂÙfÈK|yΖǡâ™^(”lDÈ©P¤uht´Å$7 ‰9dRóY•^Nò2ï¥í‘Äë«z¬ß‰-zƒËI*Y­zfEñùg©;/ O©b»*,ôŽJz®ÆÍÈhPï\ëß¾ªó(/ÛgZ½vWì¾èj$i™9ôd…pÎɰυ¾[Fãùj/Ó-⊧·ý;¯-…hKkepñwZÎTÖ¬3y‰ë¨N›Î³ÈÅp¤N‘‡Né*Æâƒ23§ê;GªüšßtÑn† pîÐ>hÿª›qäu4­¾|&¢`û@ɱñʪ ˜°— sj‰yÜi¹Ìïê~ý{)7öÇSàœQnõc#žº¶ðNú&Åt– *Ís³~¡E·ý¬øx[3¸¹Û¢wµ=3¼‰ù–Uúµ;`ˆ”ûÝNgìêå”éÈ{U½Å»˜[zc†­aRèÁ0úl,ÏÎUƒQj1“— fZ¼åV$ŒåBPÞQE¯…Ù×Gº“C®4ÌÓÇN‚kóäj:%-fë Ò?Ù¾îx<‡õ†÷ÉNÅ2ÆQÍj÷½©”ø}GÒ)€{QvsÆ â¨yq,œ¦ýbÑ‘‚¾Y?LÝ Nu$Àu¢÷k@ñw¹TzXì¨úøãÌ2 ½o"Ã)Ÿ`nôyÏ€LPî®Pê<‡!v¶{èT¦®·ÜëU$'˜øBÎ=¬‡ËºCÔCòu6ö%²Óƒ‰€k ¾ƒaDÅüûQOï›»WtÈ{¾g‡„¼mË(}þ#„ãñÿÏ’µÒ9µíµ]H|4nßÇ¡°íZ§n„=µcØïúÃo´&c«ÞÿŠî=ˆ ß"f8„ˆXêB“C脎ú˜¶žM·s1!^÷É ×î®yÝJáNˆbž=‹Öj~¬áê¡A’l>ÚÚñ‹Pk7Bk.êc¶ún#Û’Ÿ;'ïGz¸kÌ“pVCÈáã%#uè§Ã ûX‡W2¬Š`%!ðß9%8õÕ9¸Mòžê/+[âkq;Èf˜´µ:\Ðè °Aa§Š^~Þžà㟅vQkX½uö±è*Ú 3ÇŸh?~Ýj_ÚêÚ&`µŠ…¹mA¯ðä ˆ}^¨ôöÛ¦‚™ ä>;7•»N&cÑk‰ý.Œéõ¤?U1&º¤ß«=·0¹?ö‘ø„ä· µ Óg2õ3Æíë&€*øÞ 1!tQã$f ì¹T)Ñ(Re²Ù‡ÚÔYZziF ÿ© ‘_&j%-WÚˆ ¦>@l¦‘0jîIBBøÛ,vRdÔì†ÿp[Ž/íÂ؆¹lÒQ¥6_»æû-Iª[þ« b/”±î‡Jê²-Ê{ÎÂÞÐÔ¬ðɯNéRæoƒ;°ì1½Zz$©‡q~ øe0w“ÄðD¿WÔ«o–Œ.Â4 q¬ôn£¯›my8gY9$Õ*,(nŽœ,ô-õï«ã²ç*hå(z…¹„žçG+Ë/¯›`k¢;j¥OݼN¸µ×О:ldŸœË¿Â"¼Ü¼16ÿ¢â{™eZon5ÈGÈò”ÝÞ;jÆüào.®:LO¸D1#ŽNY‡ 5héÅ¿¯^‘ý„Ù¿eNÞ¬ÑÝÿ)®&¹­…ÏMékûOaÎZ¹EG­TAÃjßɪ ö[i»Lé”Àç·ÔÒ…¥¸›«¾ìˆÆŸ–hPÅGep'{Ù®8D³mÚö8ƒ8ÐA—¢ÖEkÞn‹9äjv"Â!Ár¼M¬Ñâíèo($¶¥l{ùV3ÕPéÍòŽü 7á®ÔQòv,q£ó4Lžéó8NÚd(ÓlýtüšÈ—¢$wÌfÍ9ó._Ói±wØß«^Ø•ã‹áó³Ý$i¹x¸ÂñI‘!½áŒ‚L–·MÇgéT5DŠx#ŠÇñNPPµØ˜-.#Œê‹¾™ú¾øæûçoåP9{"zdÊÀíFxýzìÝ0ðφ×]ô4*ûŽêx A9Í#}§„A`sÀ)óø1ü|uDm”½ßd{¥ã?'H |žÚ|ïé×:,rCÊp6 rW";¨Æ5‘ž^I=Æ Qœ]cËPݲØÀéŽvÄùr}?$)T$xJ K‹%§®˜ýz8¨¸g.zÚ4A£÷ ð/ŸÈ¼íPË•¯€†™‚xNsvµ"£>lœyųv÷kÁ7Gá„‚ÓN*$¼<¤y[±Ç¡¦Ð]!²­ÊR`c3@!™½ÌÿÜJqÊD(E؆(e ¬Õno¾¾ü‰Vó¾'%Ì{#À)ïS©l(fžDZTè„®ãêóg%f°%rM-æßؽ˜l®½É¸9Þ\÷°‚äóˆ¤Îˆ¼‚Õ&é&ª0ðMÈ”ùXåå\~"\þI£AbžqVØAµ‘®)]¦Š³ÜCŸÙ¦C~UþFU½ÍÆ=&R®‰“r³‹DÿpÊf~ëMø©FPˆó16_}‡âXñ[: "ªú<¼ÿâ &œ¼ý‡¼gëþñ­j{¡ÝåÕ  hkÔçþ§±ÄQgsíù6fŸ½‰bV.×Qups Çó÷'÷¹äÞå“P+A{CNYyÀŒ¿‡ì¦kÕHüÌ£5o¡…Õ£] ?‡|Wo0KÁÊ3:Jré…úûØ.МfîÀ¶.¥\InÖ_Óé³c—íD»”á*êîˆVFÁá±[gÙû+3„k” õ>nÙ•ìc]l_[°ÊGYEÄ3ÆÒ_²—Ô¨'!±76¥]í“ÅO‹°’¿ÕNÉhÕÑB‡éb$¦ì'Ûß_ά„i9ä­Ñ¤s¹Bzu,wéîK†@°»Ô¶Ë~µ9‰ib—•9‰FiÚ=éªÚ"’~1DÖ¨AˆÆ†&ñV•Ò_Å!W±[<Žj5Âu½{Ó$ˆRiî-YMb.ôߥâé…íTIDâuPâv~R·Ã9 UÙ¿4ê%Q+¿Nz¢2¢ÉìÆóAÃVÞ÷gêIFs>çàX…³5óÇ,K >³Ò˜Ç_ð3 ³P¦5•è> 8"Ä8Ít㜪^&ˆ¸#`Í=à|GžÐ‡#I/øFœi3º œ1Mâx)Óll‡®&rƒ¹ô‚Ͱ_MS*ïJš/|Ü· K´µš¿¯ñß~² jÁ¹ë®™Fã¥÷$ð{ˆw˜,(’5”V¿,OT2ëMÿ~2ã%YwÆÃX5G’—,@ÝQ×¥9k‚6¼üºƒ§-þÕG5Pjà¯)a…ÒRÔo²(ú¨Mâ¿Bˆp™[¦TZbu·©"ëɦòõ5Iƒ—1ü^ÉÊÌo{)ȆDüÄGŠtºèxlö±¡»£-Öwß®›^¨ô1ejÍ!ˆ#ݪ+õ©z²lVîËH-ò¡[þFs«á¡Ø \·»Gy!κ"0{ìržñgC˜{;-X´ŒŽ (2=”Jks±B0¹ŽÀF9‘tB!õTÝv«’ôð 9áŒÂGš}çtÉÙX^»TxE›XWp†ÉÌD’ÚÛrÍî¦ðVÍþ$Ë2ËäÚ¶wÔ*”ñÇæâÁc éw (™vˆN{…˜ž¾D&I&B„t=zàH ïz?ý,Þ¾ƒûDøpÿ2‘›-o¸„ýú7á!ñT.Á3-Þîh¿ Á‹ªó¶›>.¾> ÇÖ2fè~P•E…Ùg¨«Z~Yu¦ŠR§Y+ézsÍ?V”8¨ ÿ„röÑ‘jûjcºä Vì Æ|\›.z ép§6'7û$»1†yGTM[{ï ñJo=u¶Öºê@Pœá½—s­„KŒŒ‡°b7¶íÇwÃYÍ„’j+9©\lyþbiõ11FK­qã)†þnP¼ˆï!ÂÛÓx龟¬‰ð<ò†ëä³É²wì— V™EH` GøÞü¢jHÔÒ?+¤§½±ˆ, ÁÐOȯöƒÀ‡òˆ¤~™–©ïÛÖÍ ¥-D~£íJ™ƒ×—­Q»ˆ†wqX8&[C§æ?¥”-V‰Z.Â#u«08•Ž~?àÑ©'`c ìEhC4² pê,›Ùjêoú—g'~wElˆÛ”FÉ!&t^†= ½§¥éBð:mË!Ðmên¸x6™ÎýYo¡ôlÛ×ÿI¡1ÁêÌÑ5éãÌ‚·¬Í§èc~¥©ií¼§9GZ¶Ûù‘ÙZËZËÜÙ¾ø‰3•]©™(´Ï_ÈM^€€)Ÿ5鸆…a»uÕ6œU^óŒšÿÕÆfede5']ç–¡H ˜CåèÕ8 yJÚÇ’÷#+ÔåkÀÊ;wnÞ®|Óćœ„J´ÜrÄûM Ò†UªÊæ­ßœò¤£)1œ1sŒÁ²R‰ÄúK°µ`ÍÀدßõJsÄ‘õuWÅxªTvNÕÙåÝêäû[ (%I6-ÖkÑ»^µq:GaNÌy½‡ï‚Ú«ó×pÖ€-½”Hˆ[_à®Z8 -¨£CÊJT ØúV"¬;ÕSVYƒ6©…:+ñ=„„’ÛTúÅðߟHÏgXOWø›ãK(÷&jªò΋å3Ö ×Ï"åzÜ,¬N¶‰¡C.^ÚÐD…|=ž…bØ#Ó[úû&rc$eYñû"EÇÄXÒÏ48Þ${Ð^»eKø½‡Û})Å^ï/FA*»êiórßgfñõÓ¹í GÝéó¿L}Ež¿õ;Ã(ëh€X)áæ›»?-9xq@‚¥·]p{ûV Ì@ÊÒ ½­xG¿é÷ênJ~°¯,ÐfQiÁ¢Il%¦åòµj'œSêàøäkË'K›½1D <Â;r`ä ¤µì„1¼õ…%Žp".ƸÉ-|x¥ƒ!WGò6¥±0vĵ 9Ç…Jú”}¤¿Õ”]â^ÚL¡,J|ì¶MƒºJч|ÁΆ×681‹º‰š˜%³…~É k­ùü•zÆ®ÇÞâ>bÜÄþ9ZkÀ’°8j:ò©J¢úZ哿qØp8Œ× žPû—³€Ò÷ÁdâÆ±ÁÙOûýûöd « É„qM¼%M_SF¢Bîi–§W-[%ë ?p§¦-H'H†IȲ7žùí mOCÁdRˆâ®"½¨ø Nä@4ÿªk;§PI…؉œgXó2þÙk~¾ñ /íÂíº Cá)&¡ÿ‰ï˜4÷«™Øû+€Åͨœï÷HFLio;ž¸+¾þg5FÿNÿ<Ë*‚ÉÕ%^ Ü7·â‚’É,)“_†ï•/ „ðòæTýæ&)~ê,BÛ $„c1Oá)Á‘‘ôgÄA{FMžLhCŠðݾ™EË@À3i·ó’ðᵆo€'§)wñCî‹ø0”[}‰n²Z\˶øt2W F‘­C‘zKmCY™LZ—­ª=:F…CA¼ÄxƒåR}÷"×#‡ñÊÂ'‹1o‰÷ÐJaŒ×z}710'.² }+£÷!˜T´ÜJà§w* ¥ä†Ê í,‚”ÅAñŹ?fäÚ—=fì 8IÏø…@:Ëßå7ZéAMî£ôêƒoÉjJO©Ï+]¡‚½f„G~ÒK›Åw‘83o¥c`¾¾ þdÇurØ!ÃTÜå×ð$Tð—ÎAÅ+·ìèÝb^r¸å˜¶6— {¬ƒ™…o¯,)txm%oP4]SÞ&ì »+/Åú½çv,ûá$"ã %5Ê tèi(iÍßÛÙko„]±Ý–j¾ :ž» âù5‘è)Í¢3sTüø”õÀ'RèÝæW$)3jÄ4 °¼§Í‘² ý6ÂüjÀOÓ œà±X‡X,‚[טH²àã3·{î²¼¡nÊĹ®øE¬–gÃì˜L=`à4WçÄnûµLÝú̲Íߺ³/SBÛ¾ãN™Œ»=–„ ¦Áñvl šÚ?|6‹ŽÝk`ÝsJز)Ú7 »6!O½Û§yÙªÑ]¦äS4¶ìõðÌY™_ ÏŠÀ7^lsDå»ËžŠô}ydûk 䩎¯«x£9 ˜½YÿP鯤ž†m8JõnÓ¶KÔdÞ‘›Ôøœ3p/Ñ…År#ôÔ)6í;?q5¥™Úùù@AlŸoá¬î{ãäoHH˜¸Æý•ËÃkFNªžÆ&"A ‡8ù` ºƒEo] cOÑb»sHaw†œìbÃÎpV‹”cGö”ªQÉéÛ#q3Ÿ-w E„tš‡ZwüÔðä“ÎWy‘†³¿\²)̤ðÙ³Ë1%®$|ºŠ;êHÂàÃ%ÛÛÇØ1g+s¥‘Šöb¤~N´âP¾-jndÛ:6ÑÚ”aNgVkG9,¦˜ƒ(*2É5Ñ•ûXdßO‹|lPÈtØÓÅúNO(«õ¯†iw[÷k£Q$B¾ÊWˆäâ~!Ç×´ÕÍòCR ºŠóñœ‘’ƒBù8ƒ÷›Öp¼“…©¼±™…Œcn1N«’æÐI§Á€RÜÊåÂÌ£![’ݤäF¦/…'ËGjõ1©ÅòÐ=MS?nôEØóGû°}©ÁÄ0"‰GÝ¥°¨§À*;ýÖ‡kCJM/r2Κíè¯ÉžTx'•œ‚ 2Õp>Íð’)é]dþôË™Z® ÒuÂ]ÃâªͬnÁ„³ÌØÌ ŒÊP*7ŒÄ¾ŸcM$as"Û™£N.aO‚Öoj‹WÀÞwM.̷̽ьÇ4âÃx»^äÚd±?‹bE½¶ß +OÔg%›a| ÎCÊ'[w™¯³¾ÀŽÁòéŠ ²ÿ|‘w.+ñ+|£'HÚÏcóLÕ l3”¨Öíš?|L.¤ i¿¹œÉ´¿¡±¢®Îªž=Ö-(.káF”@:Øwxšßn4x-Ëðª™`°ÌpBž4F–F+5ýö¥0ÏÜÔ÷À`3zß`h%Éë=ˆœ´3! YGO×l–zï”xލ@€lgþSÆÁFá6’;®¥äÀqdÎÐãä´7_6¨£½Ô”ï ölÂ>ç@5„|ñh¿ó[ø¹œxÉNúü evÍ9©>—,²¯ÏÆ%&Ó[o(Sê’¥„-­G½$œY‰–ÍU˼ئéôŽ‘;Aâ@Qòa”¥÷jV£%j¦8ñ äÈ@ˆ£%#E¬ŽÕæÑgÓ´ >ÍÛÁµãèGSy£””AVé.∇CNÙWR2þ·¤ÌˆÖ•¤n°©ér–~nŸÄw;>m“½A´û„áÿhTNl€N¥Fí'¤ì5LYh7›ßJŒ€&\ó”ÿiìÀï^û¼Ç\´ ¾|«çV{> Œ£,sù 5꾨£~Tf¸§'éy=i[(NRÁ…öBžÐE®â›èŠ·ï“êîöíêÚ2báÄÀ”­Ÿ Wº}”šå¾1«xÙ™JúY„g ²#æ}äBò~¸g5&ºaï‰4„ÛË9í¥—¤™³sñ$i™óV¹}ÒÀ7£oJd¦É(Ž áxþH¥ÑÈ~¿e[ Ìðønv˜«…ðá•/2bë&7ÀŠ¿V'»Ÿ¯KõŠ«}—7L÷Ôõ,¬Ózm€ÿÔ$Á¡ÌÒÛl¤Ñ™?ˆ!ù `{n¥<¸5ùQ媓21M¾RÍub…Î4¼Eì¬ÿ;”ÔühîÜœ]O?6O—+$ÝËGB’ê‘X’66¸zT•S’£ïÉ‘_Ô1!Óß ¸Î1Á“Q 0 vÔȤ¢ç¨w#sDëMS¤j³´¿¯‘üBZwë„ñD^öÌUѯ8G* ý ×=žÃ’AO@<#èë§ÑìUö4\ ¿öcz û¼ÓÈè>ÇÍv›í™l<‹5JT=†qHõ27^N<´Ü¢Äy3÷bmåáÓí™\Œ½Ò—A„¨ÐåÁñêˆ4Sœpð]òº<ßa•~ùù:‘oåh¨u¿N€^láGà™S6úvS2Ý(UÀû¶ËrTÝ#ujq3fÿÑ4ã¥ÓÞžj˜dç³[•‘\Æü–ÜùÆ 5óæô¸V·}¦XtLÃqäOé]ÉYDóµX ¢–rµzÌ7ní¬Øºqˆ‘Ê éc¦>±Pà†³™TÑù@/¤—–¶œ·´îÅÄkòÏù›3µ,µ‰Ü'"µ4 O-²­ßHD¨àfô¤Ï 2fØc›™ Ž1 2,1˜¼»òòp¦[»Wn¥[’º‹¡Oáy®nïQ˜6}3^ðHF“Ñ*ýn¤#ö;ãÒΈ}Å·ez#å ‡G€4&òAƒ8· pc´Xè #Ò“Ò  †ä>ßIdÿƒeȆV:-r©O2­f@Á‚K’œÚ-Œ§ŽêYù­¾]8ß qñ4;•Þ3,¬­ÑÔ¹WL¹|-nZŒ‘ìˆ &ŸdHg7wÃÚ;pÉPdÑã,“ˆ1øùÃy#­2Ct„º±DWà$jÞÄðèc¸{ÛØ@³f‘ŠñÕb/k›&¢d¥IF(éÀé³|m—ˆ;›}üLÁ› üïÕmFR„à#G½½˜®‡Ê{2‚qñpè²A/Ó½žû¹×oÙ$Z:yÖU­C L£7’ˆ»ØÚ+ûK©ð¸TDð9Ffë¨ð­·’®¿Ž|3ç©vocÏq¨ ,h6Dk9üH È>ó ÜW·ü—LÁ5ЏÃ'•’›·kµ°ï\/ÔV“Å/S$›0© ƒì2Oö‡#ßt›øFë¶á£›‘èÃUÅmÌT¾¿„–Åö×ŠÃæñA²ž–dëå3ÝØãÈWâû„ågLl˜˜t­Æv%›‡\RßFµ B?ÄÈåé¡tk] 'ô£CôÌrk‡(F?PæÑ¨éVÎIÐã?^ U ˆ‘ô:Û≯½V ´Z!š)îD°F4$RÞðèM’¿–&©·R|S‘uùv‡?  ?Ð+5d‰}Ó ÏæsÙ»’3Ò쉨fZ„qMÇ8íî&$ÆÅnµÒ•<‚Gá[ûÛ”kwL¬¯46®Yá¥úÎáî±–òh´m¶à]”xäAØ¥¿[tSu¼P9‰ÕåStß+I4ØxøÀ/4…ÜýÅ8ʱ#‡G^Ç÷擯YĺrÆuØÅÈÀ$A‘¿Ñâ¾ò 4BRô±­GÖ‡2²¾(¤F«"º¯Hˆnå.mM²áR–îèµY.mYþe†0ÃìÉE¢ös&V= Ô„röò*(£I.3µVŒQsˆË•ñ௽sËz^~¿?¿—1C3B•Z`r…Öñ" 9õªzVþì¯þ)^ÉÞo8€Ãã,Ö/œ Nc]ÿ.§†1ycÕ”ƒÊv¸:29R,ý®Ø°ýÍ­”-òMù7ã9Îô!²“÷¾l/XäUhbÞvg[´ó%w"¯ªÛÅõ[-z$:Ô!X x¿v«w¶,l*ÔêÊ¡~ëá[cÔ&`’×MÂPlÌnŸlÆÌl ryoV8%ÖÅusÊ02 ú O >°ö×qˆåoËþÝëv÷É…VkýÚ_³˜Eì^‡(Gã5V´‚Jä…#‰(]Êûr¦ÂÇažDà='*ïö,v¥|[æ;FZaB\1öÔ 72µyM8+/Iimq†£'Pà¯'¤×Ù&/E¦op?ÜÕ{Tí)´êÏQ©(Ô¾L°âZ–䦿ú K\`á¢×'6EŽè¢§û.YI‚iW$uÀ>¨iAP°+þÔ›´RüÁa*#ÛU1ÚÐI9!Ž`v/ PæN|°€,r+Qd(‹ ç®~¸ f—G‹ˆM¤ÜîFò–·’môQSæ¼*¬²S12ê5’"›Y÷çKÊÇࢡ ?½BrŽdÿ$D:ÎÂyH¦ºþô…B¿’­b½ˆ—8x´v›w¢¢39c4Qk6“,¯°eLjvj}¹·8/\0¿%]B¯6)T*Ô²ô)Å„•yr?[aÒÅ!²nV\pjÇ î¼k€Ë ¹>ëC¬ Ñ{§íNF '’\1?6¬Þbi†{õxÑÐËDë#^BøìS4£Üýb~¿ÊXˤYŠ5Æôÿñƒðÿü_‘ÀÔhììê`gìlƒð¿LËf,endstream endobj 12 0 obj << /Type /Font /Subtype /Type1 /Encoding 105 0 R /FirstChar 11 /LastChar 123 /Widths 106 0 R /BaseFont /YECYWP+CMR12 /FontDescriptor 10 0 R >> endobj 10 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /YECYWP+CMR12 /ItalicAngle 0 /StemV 65 /XHeight 431 /FontBBox [-34 -251 988 750] /Flags 4 /CharSet (/ff/fi/fl/quoteright/parenleft/parenright/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/A/B/C/D/E/F/G/H/I/L/M/N/O/P/R/S/T/U/V/W/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash) /FontFile 11 0 R >> endobj 106 0 obj [571 544 544 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 272 381 381 0 762 272 326 272 490 490 490 490 490 490 490 490 490 490 490 272 272 0 762 0 0 0 734 693 707 748 666 639 768 734 353 0 0 612 897 734 762 666 0 721 544 707 734 734 1006 734 0 0 0 0 0 0 0 0 490 544 435 544 435 299 490 544 272 299 517 272 816 544 490 544 517 381 386 381 544 517 707 517 517 435 490 ] endobj 105 0 obj << /Type /Encoding /Differences [ 0 /.notdef 11/ff/fi/fl 14/.notdef 39/quoteright/parenleft/parenright 42/.notdef 43/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon 60/.notdef 61/equal 62/.notdef 65/A/B/C/D/E/F/G/H/I 74/.notdef 76/L/M/N/O/P 81/.notdef 82/R/S/T/U/V/W/X 89/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash 124/.notdef] >> endobj 8 0 obj << /Length1 839 /Length2 2152 /Length3 532 /Length 2741 /Filter /FlateDecode >> stream xÚíRy<”í¶ä«¦¨È?y'‰1#c,}„Œd ¡,™f^Œfá5£™²§cÉ^¶,Y+[–D‰RÉšFJ •5ŠÆu¾ïëôýyÎ_çwÞçŸ÷ºï뾞ëwÝnc§fH¤q4*] DëÆ–¶h,€F¢`„1âé$õžêh4`Èð4PZKw¯¶®†& Ó|XÉÓ‹(ï^#aC ‘x*`‰§{žOìhHg!C2°]›ðlA?ò‰H I:pô$Qaêk†Ì¨4û£LdøüÑò!?ž)@™gr7À³H¤QÉ,€zÀÔ­h¼»@ž“ÿ†©_Åq 2Ù OY“_ éom<…Dfý‹@£ø0è XÒˆ Dý•êþðf I ʯ]3:žL"R=É €úQ"ùáHLhC¢¼<Ùü^©Ä_MðrûnAÝÂø˜õ»=?öù½gƒ'Qéö,Ÿ?U×Èß1ú/ÌK"1g…Bóˆ¼óÇŸë/w™P 4"‰Ê{-AxŒ÷2x •2É3¬Ž¤Òè¼€—IàAƒ`këÄ¢uÓµÒw¤Ôü‰Ð( Nü ò¸àOG&ýÑš€:ôäuý~‚X@ñþ=*##3@mï^@Mƒt41VS'èßxTú÷WÈËûìAâm™ ö¢FÐ óN­‰(>c’×]"¤ÂoäYoUÕÔÛ¸)´ÿ"?¹ ÍÜWåu¥Ó×ÒËb"cBcr§Vdü¢wà>óOcsÇüÝÇ.Ÿ¾%ã4{Ù’5ê³k1ôã–Û5Ïæ'0üÖO_?)N:šÿ sºõcŽòûwë_Áùî9ûß¼—¦…uÂ]&‰ ¯TÜ ·Ýšæ[¥9xjkRºÁ®Ð3Þ‘êö ÌТ_ó6\Iä_ïv%&^>)ÄÌ̗Ѩ &çu¦"òwW9_g‘DW4bu•¿ÐÚ^WÓFLng‚—øËEÒÓ7œ›ì “Ö/k]P¶žÜGØ^o5´â-@MIaa”á ø²/ßvÊÀ·ß ¤êÅëA•¸”a"7œG_%îz/»ê†þ¨MÍÏ~¼üåf³‹Fè\g¡y3§<³ðà ëú2ùÉ…¼¡ mW[qÓ–’ÒØZ!3µ>vÞ¤ìY`±ÂµößÙ&´XÕ3ZIÞÎ3VÈä´äÅÇÖfbÃÜ!ùˆ0¶R‚üAÒøpAÿõùaíÚ$èi1Œ\œ%ŸÔthú¡p’Î@笼Ò]1£ØIo}õ7aÍùå׬>¼©–Rî­› Ã;5g\n1#ß"©õì  Ÿ=C´$÷ßwö2y€‡S§]µ%!ã–í‘§I9ÍH½ ¼4r4W"=PÑâsOhæíçÑûñ[T…Õ‡²¿¦íZ="xŒÀ¥n zÚ+RZ1'¸qgö«ØtÑÛûݰâ;®ê÷á铈ÜQ{„oq§É\gìœh2^òB­fy{)ÑÎܼÃá‚¥noÚíŽwŠîÒkÊï½8\±¤ÑG³ì–ï™V9¥U쾨Ò$ç§»M@[£ÃkùDÔÕÔSÆ‹çà–qÅM-‹gùÄàÏtNù.*Ë ä]L¨‹œˆÒ¯°±ñR”½Ïw> H˜Å;è‡1ðÏ:ÁãU×1Ћ"Å$gý[G#¼døŠRȺ` Açéj‰ÙºØÅX+8³<£a—Që°.­F|Îûȉ-Ïi#ØÛ|›Z̪ „èÍ7œQLÆžÿœg2Å‘.íÏùt>8¥ g|åRú ~˜u0FðÝóEϯ)[ïôêGÙ¿M³œûÍ×d&Þ¬¹5#eŠYÞä¢Ïi‘+ í¬oÛì ÷ò•B›,¬Ù° ªìH˜ªc÷r»9f‰Ü‡ôïâø¢›ä*;£d®ˆÈ¬vŸÇ¹¤[ÀØ›E? ºDôuß6ÐãëÉQÁ9w>*ô­o«»B¶KrÛõnhœ]™=j\P5¯¼^òÆ¥o»N3E¥V põv«žÚ3÷LÒÛ~¯Î¦®*¾IaùØTÙò›ìâ¯-˜‰K¨Ê/™ëX>*€\W9;Vèå¦'Ë–óRi˜/¤ùwÏš;b·¢nT['y”(B³™s÷'^3–Ýø ¤\Ι~ˆ‹½¥§s±d‘zí ¥! ì÷êäÊ?ý$ypÚÁšƒ÷ñeŽ˜&xˆä%º”äÅ#Êb§®óçš%$à·1Zk)m*9ëÜ*VŽž >)êè ª p9¦0{s‚³.y!Ôáqùe,cüY†Pµ¾”ô†Ca–é²+]v/k®ÿRñ ø²ÞÔŠh阡p;nÛg½fŽÿG›»OpìøTZô«Ü{ì%ÆB‘}¿1Ã`Ý:P4…òk¹£™ïeÅCî {Æ—ù*‚FÃV­ˆ.÷e¿~êB¨µ%›Î˜çLgVí{1òºÝðÂl¦’í3ówĸV dŠËʆ…±% •šd“o{:¦Ÿ™özÔ+±Q®]“r/Õ9m ÷¢kyñ\Õf¶d…[²ÃÎ)å}u®ýš´|^ãÉК:O¬¿³Ù>o„oH,t€ÉWrg7¢Ú%.Z›/ t° 3¯®ž¬0l¯BËå¾°+ZwŸ¯§=Ok¾ÏuŠàdrA0üEáVWln³ZÈ% o“ô“ö\µØë£=ýÒ!ÙóT~5â:%÷G…øÙ°¸ÃÚG>,_ëë´ƒ½\ÌÑé‰pJ»í¥±k '«Kš¼ùþš ƒŸˆæ[òø4 $-q£]ŽR“š&;Và…9J‰öbgš–ç £½÷Q·¶ö÷MFãFð¢’íå_ŠT‘fÆ÷jZúD·èbfú\Z]8¶¬’¥d_”‹éux´à¬!^4Ùð1f8‡:WdØW ¨й™UU"=¾‘ðþ1‹IÊuG=ß”,]_týÁÅ—"z?Ë4Vîô™)M©‚£=pgs·a‘›™¢Á.¬nõVbšåνlÏ«ê„B·xsKÐTƒ?\Ô•Ú:$U&Ä=žÀ>™i{ø¨ËÀw|c¥M¢ÄXºä¿¿Äá˜ãô×§W âȲâ—ûáŒâùãºBQA9ºÛ˜š7 Ÿrì¬GV‚ú|ÙC»}ó0ºÙÒÛq¿³ûô7Ìt<-Ìj©Ölâ u=_Ï?5’`–…9é̹]ïæ#ʤe€ jÒ³ LY)''²Œ6o,Ï”Ð;„9W£$äèû­¡ÆV/·è:m&{‹ ‘}Ù×L¸þ¯†Å]" =cÃ…úÓwi½À¹ƉòÌkR,Ä…ÞÝFkß ©›ÆÀý=zˆ¡$;ê–Þ·k|š•?jÔ_7Þœ{ªtëÓ/)š1„-ç4%N"ÌÜÙéÒ)¤¶ôˆ¹.e–Z¹•|VÁÔ^MGzýêPÝáa.dÕ¯ÿí­~•/¦Üÿ=<"q~PSG/¡`á7ˆú?Øÿþ'dÑi> endobj 7 0 obj << /Ascent 694 /CapHeight 683 /Descent -195 /FontName /LCZOUS+CMR17 /ItalicAngle 0 /StemV 53 /XHeight 430 /FontBBox [-33 -250 945 749] /Flags 4 /CharSet (/G/U/d/e/i/r/s/u) /FontFile 8 0 R >> endobj 108 0 obj [726 0 0 0 0 0 0 0 0 0 0 0 0 0 693 0 0 0 0 0 0 0 0 0 0 0 0 0 0 511 406 0 0 0 250 0 0 0 0 0 0 0 0 354 359 0 511 ] endobj 107 0 obj << /Type /Encoding /Differences [ 0 /.notdef 71/G 72/.notdef 85/U 86/.notdef 100/d/e 102/.notdef 105/i 106/.notdef 114/r/s 116/.notdef 117/u 118/.notdef] >> endobj 5 0 obj << /Length1 799 /Length2 1920 /Length3 532 /Length 2492 /Filter /FlateDecode >> stream xÚíRy<”ûŽ,”qì”WY“YìK ÃP"!•$cæ5&³ðÎŒÆÇ’%kÖJäWNè¤pBÈ6ŽP£²%[‹p‡nÝ{;Þû×ýÜ÷ýç}¾ßç÷|Ÿ÷ùþ4Ô\Üô¬ 4_K£2ôд9€q¸aÐ(@Á440ˆchT[4ÐffhÀšIЦÚÄÜÐØÜÐ ¦`h!‰èÏ´1:ë$ÀšB$<Ž 8áþ …¯Ç‘7ž2B€5™ ¸®Ÿ ® „‚A†Fžø‚D†\·t€êGL¾” ÌÀ¯­`¢óMÚ|“:ß"F%‡Ð†t¦ñg|'ÿ Sß‹c™d²3޲.ÿ%¦¿p9ä%É!À‰F!ê÷ÔcàwN Ĥ|ß=ÀÀ‘Ixk*‘ ¨/%KbïøáÈtp£R ß›à'·a‰u±sÃØê~ÝéF×G¢2ÜC¿é®Ó70úŸ˜ŸDb'Q Í'ò߯_§¾›fGÅÓ$*Ð72p„ ñoah€D%€,dñ-#Tƒà§øÑ ØúJML¤Ózi™òѱoˆ¿3$îB£õdà¿@C mÀ¿þ¾ Æ'èéñÍ øCLŒPÿÆÃ3!¤26î?ïØÄOY Æ á-bÏäÖÄ—GÚ•ô\Ö¡«ä—ÅvÖÇUå[ ¦‡,¤û ;\wpÇ<~†Ä‘Ê™q¬@üŒ^(ÖX‡·†¹!ãžÂ[%etŠ ÜDgñÓ^Þ‚mW[·Q®$ŽóTGïèÎîZ®¾yhmrMq&I¨üÉÀÊ|d@T× žxa×XìÔÕ{‡²A‰áôŽOoìi%4^i›¼WÁâ«<ÅÆ?zžKæ›%_uÚÜŸoùY ¥Ãò{ÙCM f™¤oåÞ2“(ý­©ÈN[è°f@qØhB륋ŸZ°±¦îwžíƒý.ëºÙ;{dS¦ujß%l²i±óù×Išay¢4•\RéÍûÚÞ'eSo\ͤm'‹§m?ÆkÚ®Q©%m¤peá‘øB •X§y¡t”©Ñ‘ʹîÈ*öœ2 <žÈ1_û5Ûâ¤a̘î'1+êltnI΄Kå”ÎQôZÂÓiAÙg<DZl ”Õëõ»Q]B •¦×–ß*sz£Ë­þý¸ãT[»K‡ÜÓ@=…T2¸[Ü•ó,CjDÝ´÷ÞüëŸÄÃ6–º‡aI··Ìèä¼÷¡<òm^y%º¦¯Ó„¶í~¸&Rê…—&+•%U<è̽˜ZQâÀ)e;•SÉäÛÍÏ£'V’Ê.Mf©ÅÇÏ]ÙËÓð ô',Z *«4ÝŸB#¼¥ä–2BT•kyg>Né.òðSU®Á´Þ¾Y+é]?w÷E§¬J›1o‚ŒzI}wÙDô2~¦ï‡Ý[#D%¹‰ˆÂ‹z‹©çÛßµíTžxßlÔ°Çßü b¡câ8ð· ÃxYO+¼öJ°Nvh©°Ý.g`´óÁ*cgùÇÖ¤ =Ðêì$Ûz8ŸLÉV³»×7­@ðÙ®h=n uqYŒÛî{p9·Ý¡³/˜)ÂÒÖ#­/ÍóöÓçˆùÑŽSN¿½×êá'ÖtKóò¼­Û@I³ýenPÄ+ÏõžS§‘*òA™GšuWþ^¸»Ðq ôýfË3’¦YF?h‰qVv„Ì[z—Á2ÆvErʲu;2ز‰cÇD£p·;oõ]8Ùcuvçí=­œ¹Ó¥OCÄ1?Mh.¸èqÞOÉ®²)åÄgÔY•èag›—ÌP¹ðµsås”eßt™µæmª¾Ñ'TT·ÆÙBlå²Ï²`æ¤Ý;E»ÒòêHƒ¦Š 4#gU1­¿+â=X¼…:©$vKRä âp­ˆš&f"5ä&{&?¢ìI VÁ/¬Å졤ÈÍÝ9ûÈuë}³¡Ifÿ6_@n°[7Í<°÷Ú“ª»LBƒpEØ|ç4ÙýJNRâ³Úwý™ÏÔ7Qk:6}Ž=±"ϾR€¼ôôyåñ$rB„Þå-_]µwzyuÝðŽîP‘þä0*=Þ|ÍóÜ¥Ö#×ÓÂŽ²oßXp£@ÛtyêI•ú?ÖØ¨¶µ¨ÝâžVEAÛ"”ŽåÍëq¶¾ZëÁK:èÒElo0ÂmÐw¥9òìž.ÃeÎXú•âÓÞÏÄ ­;.9^âîK–¨µ4?üS]òh|¨|ÈGäâ®_ÌA $$1íëþ°VÊÈlK¥kÖæß»K|˜ŒñÙM¯Pÿáû¿Àÿ„ž â ‚ƒ`làDendstream endobj 6 0 obj << /Type /Font /Subtype /Type1 /Encoding 109 0 R /FirstChar 77 /LastChar 114 /Widths 110 0 R /BaseFont /FPESCD+CMCSC10 /FontDescriptor 4 0 R >> endobj 4 0 obj << /Ascent 514 /CapHeight 683 /Descent 0 /FontName /FPESCD+CMCSC10 /ItalicAngle 0 /StemV 72 /XHeight 431 /FontBBox [14 -250 1077 750] /Flags 4 /CharSet (/M/W/a/p/r) /FontFile 5 0 R >> endobj 110 0 obj [989 0 0 0 0 0 0 0 0 0 1106 0 0 0 0 0 0 0 0 0 613 0 0 0 0 0 0 0 0 0 0 0 0 0 0 558 0 602 ] endobj 109 0 obj << /Type /Encoding /Differences [ 0 /.notdef 77/M 78/.notdef 87/W 88/.notdef 97/a 98/.notdef 112/p 113/.notdef 114/r 115/.notdef] >> endobj 19 0 obj << /Type /Pages /Count 6 /Parent 111 0 R /Kids [2 0 R 21 0 R 27 0 R 30 0 R 36 0 R 42 0 R] >> endobj 47 0 obj << /Type /Pages /Count 6 /Parent 111 0 R /Kids [45 0 R 49 0 R 52 0 R 55 0 R 58 0 R 73 0 R] >> endobj 81 0 obj << /Type /Pages /Count 2 /Parent 111 0 R /Kids [79 0 R 83 0 R] >> endobj 111 0 obj << /Type /Pages /Count 14 /Kids [19 0 R 47 0 R 81 0 R] >> endobj 112 0 obj << /Type /Catalog /Pages 111 0 R >> endobj 113 0 obj << /Producer (pdfeTeX-1.21a) /Creator (TeX) /CreationDate (D:20090304173548-05'00') /PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) >> endobj xref 0 114 0000000000 65535 f 0000002239 00000 n 0000002124 00000 n 0000000009 00000 n 0000118920 00000 n 0000116151 00000 n 0000118761 00000 n 0000115641 00000 n 0000112625 00000 n 0000115484 00000 n 0000111373 00000 n 0000097863 00000 n 0000111214 00000 n 0000096891 00000 n 0000087640 00000 n 0000096731 00000 n 0000086201 00000 n 0000072667 00000 n 0000086041 00000 n 0000119376 00000 n 0000004946 00000 n 0000004828 00000 n 0000002354 00000 n 0000072142 00000 n 0000070674 00000 n 0000071983 00000 n 0000007856 00000 n 0000007738 00000 n 0000005063 00000 n 0000011289 00000 n 0000011171 00000 n 0000007973 00000 n 0000069942 00000 n 0000062901 00000 n 0000069784 00000 n 0000012688 00000 n 0000012570 00000 n 0000011406 00000 n 0000062292 00000 n 0000059403 00000 n 0000062134 00000 n 0000016375 00000 n 0000016257 00000 n 0000012817 00000 n 0000020213 00000 n 0000020095 00000 n 0000016492 00000 n 0000119485 00000 n 0000023025 00000 n 0000022907 00000 n 0000020330 00000 n 0000026274 00000 n 0000026156 00000 n 0000023142 00000 n 0000028149 00000 n 0000028031 00000 n 0000026403 00000 n 0000030411 00000 n 0000030293 00000 n 0000028242 00000 n 0000059089 00000 n 0000057058 00000 n 0000058934 00000 n 0000056744 00000 n 0000054711 00000 n 0000056589 00000 n 0000053780 00000 n 0000045203 00000 n 0000053623 00000 n 0000044683 00000 n 0000041648 00000 n 0000044526 00000 n 0000032353 00000 n 0000032235 00000 n 0000030574 00000 n 0000040887 00000 n 0000036499 00000 n 0000040729 00000 n 0000035292 00000 n 0000035174 00000 n 0000032504 00000 n 0000119595 00000 n 0000036394 00000 n 0000036276 00000 n 0000035409 00000 n 0000041374 00000 n 0000041115 00000 n 0000045012 00000 n 0000044903 00000 n 0000054363 00000 n 0000054054 00000 n 0000056971 00000 n 0000056944 00000 n 0000059316 00000 n 0000059289 00000 n 0000062750 00000 n 0000062517 00000 n 0000070431 00000 n 0000070202 00000 n 0000072561 00000 n 0000072353 00000 n 0000087089 00000 n 0000086735 00000 n 0000097491 00000 n 0000097219 00000 n 0000112201 00000 n 0000111810 00000 n 0000115977 00000 n 0000115847 00000 n 0000119226 00000 n 0000119119 00000 n 0000119677 00000 n 0000119752 00000 n 0000119805 00000 n trailer << /Size 114 /Root 112 0 R /Info 113 0 R /ID [ ] >> startxref 120009 %%EOF mwrap-0.33/src/Makefile0000600001174600117460000000205411133213513014576 0ustar dbindeldbindelinclude ../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 gcc -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-0.33/src/lex.yy.c0000600001174600117460000014337511133213550014547 0ustar dbindeldbindel/* A lexical scanner generated by flex*/ /* Scanner skeleton version: * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #include #include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include /* Use prototypes in function declarations. */ #define YY_USE_PROTOS /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef __TURBOC__ #pragma warn -rch #pragma warn -use #include #include #define YY_USE_CONST #define YY_USE_PROTOS #endif #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif #ifdef YY_USE_PROTOS #define YY_PROTO(proto) proto #else #define YY_PROTO(proto) () #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #define YY_BUF_SIZE 16384 typedef struct yy_buffer_state *YY_BUFFER_STATE; extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* The funky do-while in the following #define is used to turn the definition * int a single C statement (which needs a semi-colon terminator). This * avoids problems with code like: * * if ( condition_holds ) * yyless( 5 ); * else * do_something_else(); * * Prior to using the do-while the compiler would get upset at the * "else" because it interpreted the "if" statement as being all * done when it reached the ';' after the yyless() call. */ /* Return all but the first 'n' matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yytext_ptr ) /* Some routines like yy_flex_realloc() are emitted as static but are not called by all lexers. This generates warnings in some compilers, notably GCC. Arrange to suppress these. */ #ifdef __GNUC__ #define YY_MAY_BE_UNUSED __attribute__((unused)) #else #define YY_MAY_BE_UNUSED #endif /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ typedef unsigned int yy_size_t; struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". */ #define YY_CURRENT_BUFFER yy_current_buffer /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart YY_PROTO(( FILE *input_file )); void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); void yy_load_buffer_state YY_PROTO(( void )); YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); static void *yy_flex_alloc YY_PROTO(( yy_size_t )); static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )) YY_MAY_BE_UNUSED; static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (yy_current_buffer->yy_at_bol) typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state YY_PROTO(( void )); static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); static int yy_get_next_buffer YY_PROTO(( void )); static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 42 #define YY_END_OF_BUFFER 43 static yyconst short int yy_accept[127] = { 0, 0, 0, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 43, 10, 9, 8, 4, 6, 10, 3, 41, 39, 40, 41, 41, 36, 41, 35, 35, 35, 35, 35, 35, 35, 24, 23, 27, 26, 27, 19, 18, 20, 16, 17, 22, 21, 12, 11, 14, 13, 15, 0, 7, 0, 0, 39, 0, 37, 38, 36, 0, 35, 0, 35, 35, 35, 35, 35, 35, 35, 0, 19, 18, 16, 14, 13, 0, 5, 0, 0, 38, 35, 35, 35, 35, 35, 28, 35, 35, 0, 25, 0, 0, 35, 35, 35, 35, 35, 35, 0, 0, 35, 33, 32, 30, 35, 35, 0, 0, 35, 31, 35, 0, 0, 29, 34, 0, 2, 1, 0 } ; static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 5, 6, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 1, 1, 1, 1, 1, 11, 12, 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 15, 16, 13, 13, 17, 13, 18, 13, 13, 13, 13, 13, 13, 19, 1, 20, 1, 13, 1, 21, 13, 22, 23, 24, 25, 13, 13, 26, 13, 13, 27, 13, 28, 29, 30, 13, 13, 31, 32, 33, 13, 34, 13, 35, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst int yy_meta[36] = { 0, 1, 2, 3, 2, 1, 1, 1, 1, 4, 4, 1, 5, 5, 5, 5, 5, 5, 5, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 } ; static yyconst short int yy_base[142] = { 0, 0, 10, 21, 0, 293, 292, 1, 11, 55, 58, 291, 290, 289, 288, 285, 280, 61, 64, 282, 297, 297, 297, 297, 259, 265, 44, 297, 69, 297, 69, 264, 213, 211, 0, 65, 68, 70, 73, 75, 77, 297, 297, 297, 297, 199, 0, 86, 297, 0, 297, 297, 297, 297, 297, 0, 87, 297, 90, 297, 185, 189, 97, 93, 297, 0, 207, 0, 10, 204, 93, 96, 100, 105, 107, 110, 113, 122, 0, 125, 0, 0, 126, 129, 297, 165, 167, 0, 127, 129, 135, 139, 141, 143, 145, 147, 156, 297, 160, 146, 152, 154, 158, 167, 169, 171, 138, 132, 174, 178, 182, 186, 188, 191, 120, 117, 194, 196, 198, 89, 87, 201, 203, 79, 297, 297, 297, 223, 228, 233, 238, 243, 248, 253, 258, 263, 265, 270, 275, 280, 285, 99 } ; static yyconst short int yy_def[142] = { 0, 127, 127, 126, 3, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 135, 126, 126, 126, 136, 136, 136, 136, 136, 136, 136, 126, 126, 126, 126, 126, 137, 126, 126, 138, 126, 126, 126, 126, 126, 139, 126, 126, 126, 126, 126, 126, 126, 135, 126, 140, 126, 141, 136, 126, 136, 136, 136, 136, 136, 136, 136, 126, 137, 126, 138, 139, 126, 126, 126, 126, 126, 140, 136, 136, 136, 136, 136, 136, 136, 136, 126, 126, 126, 126, 136, 136, 136, 136, 136, 136, 126, 126, 136, 136, 136, 136, 136, 136, 126, 126, 136, 136, 136, 126, 126, 136, 136, 126, 126, 126, 0, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126 } ; static yyconst short int yy_nxt[333] = { 0, 126, 21, 22, 44, 23, 24, 45, 25, 68, 69, 26, 21, 22, 44, 23, 24, 45, 25, 68, 69, 26, 27, 28, 29, 28, 27, 27, 30, 31, 32, 33, 27, 34, 34, 35, 34, 34, 34, 34, 27, 27, 34, 36, 34, 34, 34, 37, 34, 38, 39, 34, 34, 40, 34, 34, 34, 47, 48, 47, 47, 48, 47, 56, 57, 56, 56, 57, 56, 60, 61, 62, 64, 62, 68, 69, 64, 68, 69, 68, 69, 71, 68, 69, 68, 69, 68, 69, 79, 82, 79, 82, 83, 84, 83, 72, 64, 74, 73, 62, 64, 62, 68, 69, 88, 68, 69, 125, 75, 68, 69, 124, 76, 89, 68, 69, 68, 69, 123, 68, 69, 90, 68, 69, 96, 97, 96, 79, 82, 79, 82, 83, 84, 83, 91, 92, 68, 69, 68, 69, 120, 93, 94, 95, 68, 69, 119, 100, 68, 69, 68, 69, 68, 69, 68, 69, 68, 69, 96, 97, 96, 68, 69, 68, 69, 115, 101, 68, 69, 108, 114, 105, 102, 107, 103, 104, 68, 69, 68, 69, 68, 69, 106, 68, 69, 109, 116, 68, 69, 99, 110, 68, 69, 98, 113, 68, 69, 68, 69, 111, 68, 69, 112, 68, 69, 68, 69, 68, 69, 121, 68, 69, 68, 69, 67, 118, 66, 86, 85, 77, 117, 67, 66, 122, 20, 20, 20, 20, 20, 41, 41, 41, 41, 41, 43, 43, 43, 43, 43, 46, 46, 46, 46, 46, 49, 49, 49, 49, 49, 51, 51, 51, 51, 51, 53, 53, 53, 53, 53, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 70, 70, 78, 65, 59, 78, 78, 80, 80, 58, 80, 80, 81, 126, 54, 81, 81, 87, 87, 54, 87, 87, 52, 52, 50, 50, 42, 42, 19, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126 } ; static yyconst short int yy_chk[333] = { 0, 0, 1, 1, 7, 1, 1, 7, 1, 34, 34, 1, 2, 2, 8, 2, 2, 8, 2, 68, 68, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 9, 9, 9, 10, 10, 10, 17, 17, 17, 18, 18, 18, 26, 26, 28, 30, 28, 35, 35, 30, 36, 36, 37, 37, 35, 38, 38, 39, 39, 40, 40, 47, 56, 47, 56, 58, 58, 58, 36, 63, 38, 37, 62, 63, 62, 70, 70, 141, 71, 71, 123, 39, 72, 72, 120, 40, 71, 73, 73, 74, 74, 119, 75, 75, 72, 76, 76, 77, 77, 77, 79, 82, 79, 82, 83, 83, 83, 73, 73, 88, 88, 89, 89, 115, 74, 75, 76, 90, 90, 114, 89, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 96, 100, 100, 101, 101, 107, 90, 102, 102, 100, 106, 95, 91, 99, 92, 94, 103, 103, 104, 104, 105, 105, 98, 108, 108, 101, 108, 109, 109, 86, 102, 110, 110, 85, 105, 111, 111, 112, 112, 103, 113, 113, 104, 116, 116, 117, 117, 118, 118, 116, 121, 121, 122, 122, 69, 113, 66, 61, 60, 45, 112, 33, 32, 118, 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 129, 129, 129, 129, 129, 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 135, 135, 135, 135, 135, 136, 136, 137, 31, 25, 137, 137, 138, 138, 24, 138, 138, 139, 19, 16, 139, 139, 140, 140, 15, 140, 140, 14, 13, 12, 11, 6, 5, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "mwrap.l" #define INITIAL 0 #line 2 "mwrap.l" /* * 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 */ #define CSTATE 1 #define SSTATE 2 #define BSTATE 3 #define ASTATE 4 #define FSTATE 5 #define TSTATE 6 #define COMMSTATE 7 #define INCLSTATE 8 #line 591 "lex.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap YY_PROTO(( void )); #else extern int yywrap YY_PROTO(( void )); #endif #endif #ifndef YY_NO_UNPUT static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif #ifndef yytext_ptr static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YY_PROTO(( void )); #else static int input YY_PROTO(( void )); #endif #endif #if YY_STACK_USED static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = 0; #ifndef YY_NO_PUSH_STATE static void yy_push_state YY_PROTO(( int new_state )); #endif #ifndef YY_NO_POP_STATE static void yy_pop_state YY_PROTO(( void )); #endif #ifndef YY_NO_TOP_STATE static int yy_top_state YY_PROTO(( void )); #endif #else #define YY_NO_PUSH_STATE 1 #define YY_NO_POP_STATE 1 #define YY_NO_TOP_STATE 1 #endif #ifdef YY_MALLOC_DECL YY_MALLOC_DECL #else #if __STDC__ #ifndef __cplusplus #include #endif #else /* Just try to get by without declaring the routines. This will fail * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) * or sizeof(void*) != sizeof(int). */ #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( yy_current_buffer->yy_is_interactive ) \ { \ int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL int yylex YY_PROTO(( void )) #endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp = NULL, *yy_bp = NULL; register int yy_act; #line 97 "mwrap.l" #line 744 "lex.yy.c" if ( yy_init ) { yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yy_start ) yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yy_c_buf_p; /* Support of yytext. */ *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 127 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 297 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yy_hold_char; yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 98 "mwrap.l" { if (mbatching_flag && outfp) fclose(outfp); BEGIN FSTATE; return NON_C_LINE; } YY_BREAK case 2: YY_RULE_SETUP #line 105 "mwrap.l" { BEGIN INCLSTATE; return NON_C_LINE; } YY_BREAK case 3: YY_RULE_SETUP #line 107 "mwrap.l" { if (mbatching_flag && outfp) fclose(outfp); done_at_switch = 0; BEGIN ASTATE; return NON_C_LINE; } YY_BREAK case 4: YY_RULE_SETUP #line 115 "mwrap.l" { BEGIN CSTATE; } YY_BREAK case 5: YY_RULE_SETUP #line 116 "mwrap.l" { BEGIN BSTATE; ++linenum; return NON_C_LINE; } YY_BREAK case 6: YY_RULE_SETUP #line 117 "mwrap.l" { BEGIN SSTATE; return NON_C_LINE; } YY_BREAK case 7: YY_RULE_SETUP #line 118 "mwrap.l" { BEGIN COMMSTATE; return NON_C_LINE; } YY_BREAK case 8: YY_RULE_SETUP #line 120 "mwrap.l" { if (outfp) fprintf(outfp, "%s", yytext); ++linenum; BEGIN 0; return NON_C_LINE; } YY_BREAK case 9: YY_RULE_SETUP #line 124 "mwrap.l" { if (outfp) fprintf(outfp, "%s", yytext); } YY_BREAK case 10: YY_RULE_SETUP #line 125 "mwrap.l" { if (outfp) fprintf(outfp, "%s", yytext); BEGIN TSTATE; return NON_C_LINE; } YY_BREAK case 11: YY_RULE_SETUP #line 129 "mwrap.l" { ++linenum; BEGIN 0; } YY_BREAK case 12: YY_RULE_SETUP #line 130 "mwrap.l" ; YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(CSTATE): case YY_STATE_EOF(SSTATE): case YY_STATE_EOF(BSTATE): case YY_STATE_EOF(ASTATE): case YY_STATE_EOF(FSTATE): case YY_STATE_EOF(TSTATE): case YY_STATE_EOF(COMMSTATE): case YY_STATE_EOF(INCLSTATE): #line 132 "mwrap.l" { 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; } } YY_BREAK case 13: YY_RULE_SETUP #line 144 "mwrap.l" ; YY_BREAK case 14: YY_RULE_SETUP #line 145 "mwrap.l" { 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; } YY_BREAK case 15: YY_RULE_SETUP #line 162 "mwrap.l" { ++linenum; BEGIN 0; } YY_BREAK case 16: YY_RULE_SETUP #line 164 "mwrap.l" { 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); } YY_BREAK case 17: YY_RULE_SETUP #line 178 "mwrap.l" { ++linenum; BEGIN 0; } YY_BREAK case 18: YY_RULE_SETUP #line 180 "mwrap.l" ; YY_BREAK case 19: YY_RULE_SETUP #line 181 "mwrap.l" { 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; } YY_BREAK case 20: YY_RULE_SETUP #line 193 "mwrap.l" { ++linenum; BEGIN 0; } YY_BREAK case 21: YY_RULE_SETUP #line 195 "mwrap.l" { if (outfp) fprintf(outfp, "%s", yytext); ++ linenum; BEGIN 0; } YY_BREAK case 22: YY_RULE_SETUP #line 196 "mwrap.l" { if (outfp) fprintf(outfp, "%s", yytext); } YY_BREAK case 23: YY_RULE_SETUP #line 198 "mwrap.l" { if (outcfp) fprintf(outcfp, "%s", yytext); ++linenum; BEGIN 0; } YY_BREAK case 24: YY_RULE_SETUP #line 199 "mwrap.l" { if (outcfp) fprintf(outcfp, "%s", yytext); } YY_BREAK case 25: YY_RULE_SETUP #line 201 "mwrap.l" { ++linenum; BEGIN 0; } YY_BREAK case 26: YY_RULE_SETUP #line 202 "mwrap.l" { if (outcfp) fprintf(outcfp, "%s", yytext); ++linenum; } YY_BREAK case 27: YY_RULE_SETUP #line 203 "mwrap.l" { if (outcfp) fprintf(outcfp, "%s", yytext); } YY_BREAK case 28: YY_RULE_SETUP #line 205 "mwrap.l" { return NEW; } YY_BREAK case 29: YY_RULE_SETUP #line 206 "mwrap.l" { return FORTRAN; } YY_BREAK case 30: YY_RULE_SETUP #line 207 "mwrap.l" { return INPUT; } YY_BREAK case 31: YY_RULE_SETUP #line 208 "mwrap.l" { return OUTPUT; } YY_BREAK case 32: YY_RULE_SETUP #line 209 "mwrap.l" { return INOUT; } YY_BREAK case 33: YY_RULE_SETUP #line 210 "mwrap.l" { return CLASS; } YY_BREAK case 34: YY_RULE_SETUP #line 211 "mwrap.l" { return TYPEDEF; } YY_BREAK case 35: YY_RULE_SETUP #line 213 "mwrap.l" { yylval.string = mwrap_strdup(yytext); return ID; } YY_BREAK case 36: YY_RULE_SETUP #line 217 "mwrap.l" { yylval.string = mwrap_strdup(yytext); return NUMBER; } YY_BREAK case 37: YY_RULE_SETUP #line 221 "mwrap.l" { yylval.string = mwrap_strdup(yytext); return STRING; } YY_BREAK case 38: YY_RULE_SETUP #line 225 "mwrap.l" ; YY_BREAK case 39: YY_RULE_SETUP #line 227 "mwrap.l" ; YY_BREAK case 40: YY_RULE_SETUP #line 228 "mwrap.l" { ++linenum; BEGIN 0; } YY_BREAK case 41: YY_RULE_SETUP #line 229 "mwrap.l" return yytext[0]; YY_BREAK case 42: YY_RULE_SETUP #line 231 "mwrap.l" ECHO; YY_BREAK #line 1124 "lex.yy.c" case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yy_n_chars = yy_current_buffer->yy_n_chars; yy_current_buffer->yy_input_file = yyin; yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { yy_did_buffer_switch_on_eof = 0; if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yy_c_buf_p = &yy_current_buffer->yy_ch_buf[yy_n_chars]; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer() { register char *dest = yy_current_buffer->yy_ch_buf; register char *source = yytext_ptr; register int number_to_move, i; int ret_val; if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ #ifdef YY_USES_REJECT YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); #else /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yy_flex_realloc( (void *) b->yy_ch_buf, b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; #endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); yy_current_buffer->yy_n_chars = yy_n_chars; } if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; yy_n_chars += number_to_move; yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state() { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = yy_start; for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 127 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ #ifdef YY_USE_PROTOS static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) #else static yy_state_type yy_try_NUL_trans( yy_current_state ) yy_state_type yy_current_state; #endif { register int yy_is_jam; register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 127 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 126); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #ifdef YY_USE_PROTOS static void yyunput( int c, register char *yy_bp ) #else static void yyunput( c, yy_bp ) int c; register char *yy_bp; #endif { register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yy_hold_char; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = yy_n_chars + 2; register char *dest = &yy_current_buffer->yy_ch_buf[ yy_current_buffer->yy_buf_size + 2]; register char *source = &yy_current_buffer->yy_ch_buf[number_to_move]; while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); yy_current_buffer->yy_n_chars = yy_n_chars = yy_current_buffer->yy_buf_size; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; yytext_ptr = yy_bp; yy_hold_char = *yy_cp; yy_c_buf_p = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput() #else static int input() #endif { int c; *yy_c_buf_p = yy_hold_char; if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ *yy_c_buf_p = '\0'; else { /* need more input */ int offset = yy_c_buf_p - yytext_ptr; ++yy_c_buf_p; switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /* fall through */ case EOB_ACT_END_OF_FILE: { if ( yywrap() ) return EOF; if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + offset; break; } } } c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ *yy_c_buf_p = '\0'; /* preserve yytext */ yy_hold_char = *++yy_c_buf_p; return c; } #endif /* YY_NO_INPUT */ #ifdef YY_USE_PROTOS void yyrestart( FILE *input_file ) #else void yyrestart( input_file ) FILE *input_file; #endif { if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_init_buffer( yy_current_buffer, input_file ); yy_load_buffer_state(); } #ifdef YY_USE_PROTOS void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) #else void yy_switch_to_buffer( new_buffer ) YY_BUFFER_STATE new_buffer; #endif { if ( yy_current_buffer == new_buffer ) return; if ( yy_current_buffer ) { /* Flush out information for old buffer. */ *yy_c_buf_p = yy_hold_char; yy_current_buffer->yy_buf_pos = yy_c_buf_p; yy_current_buffer->yy_n_chars = yy_n_chars; } yy_current_buffer = new_buffer; yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yy_did_buffer_switch_on_eof = 1; } #ifdef YY_USE_PROTOS void yy_load_buffer_state( void ) #else void yy_load_buffer_state() #endif { yy_n_chars = yy_current_buffer->yy_n_chars; yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; yyin = yy_current_buffer->yy_input_file; yy_hold_char = *yy_c_buf_p; } #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) #else YY_BUFFER_STATE yy_create_buffer( file, size ) FILE *file; int size; #endif { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } #ifdef YY_USE_PROTOS void yy_delete_buffer( YY_BUFFER_STATE b ) #else void yy_delete_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; if ( b == yy_current_buffer ) yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yy_flex_free( (void *) b->yy_ch_buf ); yy_flex_free( (void *) b ); } #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) #else void yy_init_buffer( b, file ) YY_BUFFER_STATE b; FILE *file; #endif { yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; #if YY_ALWAYS_INTERACTIVE b->yy_is_interactive = 1; #else #if YY_NEVER_INTERACTIVE b->yy_is_interactive = 0; #else b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; #endif #endif } #ifdef YY_USE_PROTOS void yy_flush_buffer( YY_BUFFER_STATE b ) #else void yy_flush_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == yy_current_buffer ) yy_load_buffer_state(); } #ifndef YY_NO_SCAN_BUFFER #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) #else YY_BUFFER_STATE yy_scan_buffer( base, size ) char *base; yy_size_t size; #endif { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } #endif #ifndef YY_NO_SCAN_STRING #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) #else YY_BUFFER_STATE yy_scan_string( yy_str ) yyconst char *yy_str; #endif { int len; for ( len = 0; yy_str[len]; ++len ) ; return yy_scan_bytes( yy_str, len ); } #endif #ifndef YY_NO_SCAN_BYTES #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) #else YY_BUFFER_STATE yy_scan_bytes( bytes, len ) yyconst char *bytes; int len; #endif { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = len + 2; buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < len; ++i ) buf[i] = bytes[i]; buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #endif #ifndef YY_NO_PUSH_STATE #ifdef YY_USE_PROTOS static void yy_push_state( int new_state ) #else static void yy_push_state( new_state ) int new_state; #endif { if ( yy_start_stack_ptr >= yy_start_stack_depth ) { yy_size_t new_size; yy_start_stack_depth += YY_START_STACK_INCR; new_size = yy_start_stack_depth * sizeof( int ); if ( ! yy_start_stack ) yy_start_stack = (int *) yy_flex_alloc( new_size ); else yy_start_stack = (int *) yy_flex_realloc( (void *) yy_start_stack, new_size ); if ( ! yy_start_stack ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } yy_start_stack[yy_start_stack_ptr++] = YY_START; BEGIN(new_state); } #endif #ifndef YY_NO_POP_STATE static void yy_pop_state() { if ( --yy_start_stack_ptr < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN(yy_start_stack[yy_start_stack_ptr]); } #endif #ifndef YY_NO_TOP_STATE static int yy_top_state() { return yy_start_stack[yy_start_stack_ptr - 1]; } #endif #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif #ifdef YY_USE_PROTOS static void yy_fatal_error( yyconst char msg[] ) #else static void yy_fatal_error( msg ) char msg[]; #endif { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ yytext[yyleng] = yy_hold_char; \ yy_c_buf_p = yytext + n; \ yy_hold_char = *yy_c_buf_p; \ *yy_c_buf_p = '\0'; \ yyleng = n; \ } \ while ( 0 ) /* Internal utility routines. */ #ifndef yytext_ptr #ifdef YY_USE_PROTOS static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) #else static void yy_flex_strncpy( s1, s2, n ) char *s1; yyconst char *s2; int n; #endif { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN #ifdef YY_USE_PROTOS static int yy_flex_strlen( yyconst char *s ) #else static int yy_flex_strlen( s ) yyconst char *s; #endif { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif #ifdef YY_USE_PROTOS static void *yy_flex_alloc( yy_size_t size ) #else static void *yy_flex_alloc( size ) yy_size_t size; #endif { return (void *) malloc( size ); } #ifdef YY_USE_PROTOS static void *yy_flex_realloc( void *ptr, yy_size_t size ) #else static void *yy_flex_realloc( ptr, size ) void *ptr; yy_size_t size; #endif { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } #ifdef YY_USE_PROTOS static void yy_flex_free( void *ptr ) #else static void yy_flex_free( ptr ) void *ptr; #endif { free( ptr ); } #if YY_MAIN int main() { yylex(); return 0; } #endif #line 231 "mwrap.l" mwrap-0.33/src/mwrap-ast.cc0000600001174600117460000001404311133213513015361 0ustar dbindeldbindel/* * 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", "char", "ulong", "uint", "uchar", "bool", "size_t", NULL}; for (const char** s = scalar_types; *s; ++s) add_scalar_type(*s); } 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 += 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-0.33/src/mwrap-ast.h0000600001174600117460000001070011133213513015217 0ustar dbindeldbindel/* * 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(); 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_file(FILE* fp, Func* f); 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; #endif /* MWRAP_AST_H */ mwrap-0.33/src/mwrap-cgen.cc0000600001174600117460000011605111133213513015510 0ustar dbindeldbindel/* * 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) { 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); } void mex_define_zcopiers(FILE* fp, const char* name, const char* ztype) { 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); } void mex_define_copiers(FILE* fp) { 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_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, "#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*", v->name); else fprintf(fp, "%s*", v->basetype, v->name); 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 && *mxGetPr(a) == 0)\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", "int", 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_ = (int) 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, "double") == 0 && v->iospec == 'i') fprintf(fp, " in%d_ = mxGetPr(prhs[%d]);\n", 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); fprintf(fp, " } else\n" " in%d_ = NULL;\n", v->input_label, v->basetype); } 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) fprintf(fp, " in%d_ = (%s) mxWrapGetScalar(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 (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, " 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 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 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 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 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[128]; 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, " plhs[%d] = mxCreateDoubleMatrix(1, 1, mxREAL);\n" " *mxGetPr(plhs[%d]) = %s;\n", 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, " plhs[%d] = mxCreateDoubleMatrix(1, 1, mxCOMPLEX);\n" " *mxGetPr(plhs[%d]) = real_%s(%s);\n" " *mxGetPi(plhs[%d]) = imag_%s(%s);\n", 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) 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, "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"; void print_mex_file(FILE* fp, Func* f) { fprintf(fp, mwrap_banner); fprintf(fp, mex_header); if (mw_use_c99_complex) mex_c99_complex(fp); else if (mw_use_cpp_complex) mex_cpp_complex(fp); 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, mexBase); print_mex_else_cases(fp, f); fprintf(fp, "}\n\n"); } mwrap-0.33/src/mwrap-mgen.cc0000600001174600117460000000424211133213513015520 0ustar dbindeldbindel/* * 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", v->name); 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-0.33/src/mwrap-support.c0000600001174600117460000001370211133213513016144 0ustar dbindeldbindel/* Code generated by mwrap */ /* 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 #ifndef ulong # define ulong unsigned long #endif #ifndef uint # define uint unsigned int #endif #ifndef uchar # define uchar unsigned char #endif /* * Records for call profile. */ int* mexprofrecord_= NULL; /* * Support routines for copying data into and out of the MEX stubs */ void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e) { void* p = 0; mxArray* ap; 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; int 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; \ int arraylen; \ int i; \ T* p; \ double* q; \ if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ *e = "Invalid array argument"; \ 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, int n) \ { \ int i; \ double* p = mxGetPr(a); \ for (i = 0; i < n; ++i) \ *p++ = *q++; \ } #define mxWrapReturnDef(func, T) \ mxArray* func(const T* q, int m, int n) \ { \ int 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; \ int arraylen; \ int i; \ T* p; \ double* qr; \ double* qi; \ if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \ *e = "Invalid array argument"; \ 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, int n) \ { \ int 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, int m, int n) \ { \ int 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; \ } \ } mwrap-0.33/src/mwrap-support.h0000600001174600117460000001711711133213555016163 0ustar dbindeldbindel/* * Auto-generated by stringify */ const char* mex_header = "/* Code generated by mwrap */\n" "/*\n" " Copyright statement for mwrap:\n" "\n" " mwrap -- MEX file generation for MATLAB and Octave\n" " Copyright (c) 2007-2008 David Bindel\n" "\n" " Permission is hereby granted, free of charge, to any person obtaining a copy\n" " of this software and associated documentation files (the \"Software\"), to deal\n" " in the Software without restriction, including without limitation the rights\n" " to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" " copies of the Software, and to permit persons to whom the Software is\n" " furnished to do so, subject to the following conditions:\n" "\n" " The above copyright notice and this permission notice shall be included in\n" " all copies or substantial portions of the Software.\n" "\n" " You may distribute a work that contains part or all of the source code\n" " generated by mwrap under the terms of your choice.\n" "\n" " THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" " IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" " FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" " AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" " LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" " OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n" " THE SOFTWARE.\n" "*/\n" "\n" "#include \n" "#include \n" "#include \n" "\n" "\n" "#ifndef ulong\n" "# define ulong unsigned long\n" "#endif\n" "#ifndef uint\n" "# define uint unsigned int\n" "#endif\n" "#ifndef uchar\n" "# define uchar unsigned char\n" "#endif\n" "\n" "\n" "/*\n" " * Records for call profile.\n" " */\n" "int* mexprofrecord_= NULL;\n" "\n" "\n" "/*\n" " * Support routines for copying data into and out of the MEX stubs\n" " */\n" "\n" "void* mxWrapGetP(const mxArray* a, const char* fmt, const char** e)\n" "{\n" " void* p = 0;\n" " mxArray* ap;\n" " if (mxGetClassID(a) == mxDOUBLE_CLASS && \n" " mxGetM(a)*mxGetN(a) == 1 && *mxGetPr(a) == 0)\n" " return p;\n" " if (mxIsChar(a)) {\n" " char pbuf[128];\n" " mxGetString(a, pbuf, sizeof(pbuf));\n" " sscanf(pbuf, fmt, &p);\n" " } \n" "#ifdef R2008OO\n" " else if (ap = mxGetProperty(a, 0, \"mwptr\")) {\n" " return mxWrapGetP(ap, fmt, e);\n" " }\n" "#endif\n" " if (p == 0)\n" " *e = \"Invalid pointer\";\n" " return p;\n" "}\n" "\n" "mxArray* mxWrapCreateP(void* p, const char* fmt)\n" "{\n" " if (p == 0) {\n" " mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL);\n" " *mxGetPr(z) = 0;\n" " return z;\n" " } else {\n" " char pbuf[128];\n" " sprintf(pbuf, fmt, p);\n" " return mxCreateString(pbuf);\n" " }\n" "}\n" "\n" "mxArray* mxWrapStrncpy(const char* s)\n" "{\n" " if (s) {\n" " return mxCreateString(s);\n" " } else {\n" " mxArray* z = mxCreateDoubleMatrix(1,1, mxREAL);\n" " *mxGetPr(z) = 0;\n" " return z;\n" " }\n" "}\n" "\n" "double mxWrapGetScalar(const mxArray* a, const char** e)\n" "{\n" " if (!a || mxGetClassID(a) != mxDOUBLE_CLASS || mxGetM(a)*mxGetN(a) != 1) {\n" " *e = \"Invalid scalar argument\";\n" " return 0;\n" " }\n" " return *mxGetPr(a);\n" "}\n" "\n" "char* mxWrapGetString(const mxArray* a, const char** e)\n" "{\n" " char* s;\n" " int slen;\n" " if (!a || (!mxIsChar(a) && mxGetM(a)*mxGetN(a) > 0)) {\n" " *e = \"Invalid string argument\";\n" " return NULL;\n" " }\n" " slen = mxGetM(a)*mxGetN(a) + 1;\n" " s = (char*) mxMalloc(slen);\n" " if (mxGetM(a)*mxGetN(a) == 0)\n" " *s = 0;\n" " else\n" " mxGetString(a, s, slen);\n" " return s;\n" "}\n" "\n" "\n" "#define mxWrapGetArrayDef(func, T) \\\n" "T* func(const mxArray* a, const char** e) \\\n" "{ \\\n" " T* array; \\\n" " int arraylen; \\\n" " int i; \\\n" " T* p; \\\n" " double* q; \\\n" " if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \\\n" " *e = \"Invalid array argument\"; \\\n" " return 0; \\\n" " } \\\n" " arraylen = mxGetM(a)*mxGetN(a); \\\n" " array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \\\n" " p = array; \\\n" " q = mxGetPr(a); \\\n" " for (i = 0; i < arraylen; ++i) \\\n" " *p++ = (T) (*q++); \\\n" " return array; \\\n" "}\n" "\n" "\n" "#define mxWrapCopyDef(func, T) \\\n" "void func(mxArray* a, const T* q, int n) \\\n" "{ \\\n" " int i; \\\n" " double* p = mxGetPr(a); \\\n" " for (i = 0; i < n; ++i) \\\n" " *p++ = *q++; \\\n" "}\n" "\n" "\n" "#define mxWrapReturnDef(func, T) \\\n" "mxArray* func(const T* q, int m, int n) \\\n" "{ \\\n" " int i; \\\n" " double* p; \\\n" " if (!q) { \\\n" " return mxCreateDoubleMatrix(0,0, mxREAL); \\\n" " } else { \\\n" " mxArray* a = mxCreateDoubleMatrix(m,n, mxREAL); \\\n" " p = mxGetPr(a); \\\n" " for (i = 0; i < m*n; ++i) \\\n" " *p++ = *q++; \\\n" " return a; \\\n" " } \\\n" "}\n" "\n" "\n" "#define mxWrapGetScalarZDef(func, T, ZT, setz) \\\n" "void func(T* z, const mxArray* a) \\\n" "{ \\\n" " double* pr = mxGetPr(a); \\\n" " double* pi = mxGetPi(a); \\\n" " setz(z, (ZT) *pr, (pi ? (ZT) *pi : (ZT) 0)); \\\n" "}\n" "\n" "\n" "#define mxWrapGetArrayZDef(func, T, ZT, setz) \\\n" "T* func(const mxArray* a, const char** e) \\\n" "{ \\\n" " T* array; \\\n" " int arraylen; \\\n" " int i; \\\n" " T* p; \\\n" " double* qr; \\\n" " double* qi; \\\n" " if (!a || mxGetClassID(a) != mxDOUBLE_CLASS) { \\\n" " *e = \"Invalid array argument\"; \\\n" " return 0; \\\n" " } \\\n" " arraylen = mxGetM(a)*mxGetN(a); \\\n" " array = (T*) mxMalloc(mxGetM(a)*mxGetN(a) * sizeof(T)); \\\n" " p = array; \\\n" " qr = mxGetPr(a); \\\n" " qi = mxGetPi(a); \\\n" " for (i = 0; i < arraylen; ++i) { \\\n" " ZT val_qr = *qr++; \\\n" " ZT val_qi = (qi ? (ZT) *qi++ : (ZT) 0); \\\n" " setz(p, val_qr, val_qi); \\\n" " ++p; \\\n" " } \\\n" " return array; \\\n" "}\n" "\n" "\n" "#define mxWrapCopyZDef(func, T, real, imag) \\\n" "void func(mxArray* a, const T* q, int n) \\\n" "{ \\\n" " int i; \\\n" " double* pr = mxGetPr(a); \\\n" " double* pi = mxGetPi(a); \\\n" " for (i = 0; i < n; ++i) { \\\n" " *pr++ = real(*q); \\\n" " *pi++ = imag(*q); \\\n" " ++q; \\\n" " } \\\n" "}\n" "\n" "\n" "#define mxWrapReturnZDef(func, T, real, imag) \\\n" "mxArray* func(const T* q, int m, int n) \\\n" "{ \\\n" " int i; \\\n" " double* pr; \\\n" " double* pi; \\\n" " if (!q) { \\\n" " return mxCreateDoubleMatrix(0,0, mxCOMPLEX); \\\n" " } else { \\\n" " mxArray* a = mxCreateDoubleMatrix(m,n, mxCOMPLEX); \\\n" " pr = mxGetPr(a); \\\n" " pi = mxGetPi(a); \\\n" " for (i = 0; i < m*n; ++i) { \\\n" " *pr++ = real(*q); \\\n" " *pi++ = imag(*q); \\\n" " ++q; \\\n" " } \\\n" " return a; \\\n" " } \\\n" "}\n" "\n"; mwrap-0.33/src/mwrap-typecheck.cc0000600001174600117460000002466211133213513016561 0ustar dbindeldbindel/* * 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", v->name); 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-0.33/src/mwrap.cc0000600001174600117460000016110111133213550014573 0ustar dbindeldbindel/* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NON_C_LINE = 258, NEW = 259, TYPEDEF = 260, CLASS = 261, FORTRAN = 262, ID = 263, NUMBER = 264, STRING = 265, INPUT = 266, OUTPUT = 267, INOUT = 268 }; #endif /* Tokens. */ #define NON_C_LINE 258 #define NEW 259 #define TYPEDEF 260 #define CLASS 261 #define FORTRAN 262 #define ID 263 #define NUMBER 264 #define STRING 265 #define INPUT 266 #define OUTPUT 267 #define INOUT 268 /* Copy the first part of user declarations. */ #line 1 "mwrap.y" /* * 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(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 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 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; } /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 1 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE #line 77 "mwrap.y" { char* string; struct Func* func; struct Var* var; struct TypeQual* qual; struct Expr* expr; struct InheritsDecl* inherits; char c; } /* Line 193 of yacc.c. */ #line 208 "mwrap.cc" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 216 of yacc.c. */ #line 221 "mwrap.cc" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int i) #else static int YYID (i) int i; #endif { return i; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 28 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 75 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 27 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 20 /* YYNRULES -- Number of rules. */ #define YYNRULES 49 /* YYNRULES -- Number of states. */ #define YYNSTATES 81 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 268 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, 2, 18, 19, 20, 2, 17, 24, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 15, 2, 14, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 23, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 6, 7, 11, 13, 15, 17, 19, 22, 27, 33, 36, 40, 41, 47, 50, 51, 55, 56, 59, 63, 67, 71, 76, 81, 85, 90, 94, 99, 101, 103, 105, 106, 108, 110, 112, 114, 117, 121, 124, 125, 129, 130, 132, 134, 141, 143, 146 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 28, 0, -1, 29, 28, -1, -1, 37, 14, 34, -1, 34, -1, 30, -1, 31, -1, 3, -1, 1, 15, -1, 5, 8, 8, 15, -1, 6, 8, 16, 32, 15, -1, 8, 33, -1, 17, 8, 33, -1, -1, 46, 18, 35, 19, 15, -1, 38, 36, -1, -1, 17, 38, 36, -1, -1, 8, 8, -1, 8, 40, 8, -1, 8, 8, 41, -1, 39, 8, 8, -1, 39, 8, 40, 8, -1, 39, 8, 8, 41, -1, 39, 8, 9, -1, 39, 8, 40, 9, -1, 39, 8, 10, -1, 39, 8, 40, 10, -1, 11, -1, 12, -1, 13, -1, -1, 20, -1, 21, -1, 41, -1, 42, -1, 42, 21, -1, 22, 43, 23, -1, 45, 44, -1, -1, 17, 45, 44, -1, -1, 8, -1, 9, -1, 8, 24, 25, 8, 26, 8, -1, 8, -1, 7, 8, -1, 4, 8, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { 0, 103, 103, 103, 106, 114, 121, 122, 123, 124, 127, 145, 152, 155, 156, 158, 161, 162, 165, 166, 168, 169, 170, 172, 173, 174, 176, 177, 179, 180, 183, 184, 185, 186, 189, 190, 191, 194, 195, 197, 200, 201, 204, 205, 208, 209, 212, 213, 214, 217 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "NON_C_LINE", "NEW", "TYPEDEF", "CLASS", "FORTRAN", "ID", "NUMBER", "STRING", "INPUT", "OUTPUT", "INOUT", "'='", "';'", "':'", "','", "'('", "')'", "'*'", "'&'", "'['", "']'", "'-'", "'>'", "'.'", "$accept", "statements", "statement", "tdef", "classdef", "inheritslist", "inheritsrest", "funcall", "args", "argsrest", "basevar", "var", "iospec", "quals", "aqual", "arrayspec", "exprs", "exprrest", "expr", "func", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 61, 59, 58, 44, 40, 41, 42, 38, 91, 93, 45, 62, 46 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 27, 28, 28, 29, 29, 29, 29, 29, 29, 30, 31, 32, 33, 33, 34, 35, 35, 36, 36, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 41, 41, 42, 43, 43, 44, 44, 45, 45, 46, 46, 46, 46 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 2, 0, 3, 1, 1, 1, 1, 2, 4, 5, 2, 3, 0, 5, 2, 0, 3, 0, 2, 3, 3, 3, 4, 4, 3, 4, 3, 4, 1, 1, 1, 0, 1, 1, 1, 1, 2, 3, 2, 0, 3, 0, 1, 1, 6, 1, 2, 2 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 0, 0, 8, 0, 0, 0, 0, 47, 0, 0, 6, 7, 5, 0, 0, 9, 49, 0, 0, 48, 20, 34, 35, 41, 0, 0, 36, 37, 1, 2, 0, 17, 0, 0, 22, 44, 45, 0, 43, 0, 21, 38, 47, 4, 30, 31, 32, 0, 19, 0, 10, 14, 0, 39, 0, 40, 0, 0, 33, 16, 0, 0, 12, 11, 43, 0, 15, 19, 23, 26, 28, 0, 14, 42, 46, 18, 25, 24, 27, 29, 13 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 8, 9, 10, 11, 52, 62, 12, 47, 59, 13, 48, 49, 25, 26, 27, 37, 55, 38, 14 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -21 static const yytype_int8 yypact[] = { 21, -10, -21, 4, 8, 15, 29, -7, 38, 21, -21, -21, -21, 27, 24, -21, -21, 35, 28, -21, 25, -21, -21, 23, 20, 41, -21, 30, -21, -21, 32, 22, 31, 42, -21, -21, -21, 33, 36, 44, -21, -21, 34, -21, -21, -21, -21, 40, 37, 47, -21, 43, 46, -21, 23, -21, 39, 48, -9, -21, -2, 49, -21, -21, 36, 54, -21, 37, 25, -21, -21, 1, 43, -21, -21, -21, -21, -21, -21, -21, -21 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -21, 55, -21, -21, -21, -21, -6, 45, -21, 0, -21, 10, -21, 9, -20, -21, -21, 6, 17, -21 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -34 static const yytype_int8 yytable[] = { 34, 20, 44, 45, 46, 15, 68, 69, 70, 77, 78, 79, 16, 21, 22, 23, 17, 24, 21, 22, 23, -3, 1, 18, 2, 3, 4, 5, 6, 7, -33, 35, 36, 44, 45, 46, 3, 19, 28, 6, 42, 30, 31, 32, 33, 39, 50, 23, 76, 40, 51, 41, 56, 54, 58, 60, 53, 72, 24, 57, 61, 63, 74, 66, 29, 65, 80, 75, 67, 71, 73, 64, 0, 0, 0, 43 }; static const yytype_int8 yycheck[] = { 20, 8, 11, 12, 13, 15, 8, 9, 10, 8, 9, 10, 8, 20, 21, 22, 8, 24, 20, 21, 22, 0, 1, 8, 3, 4, 5, 6, 7, 8, 8, 8, 9, 11, 12, 13, 4, 8, 0, 7, 8, 14, 18, 8, 16, 25, 15, 22, 68, 8, 8, 21, 8, 17, 17, 8, 23, 8, 24, 19, 17, 15, 8, 15, 9, 26, 72, 67, 58, 60, 64, 54, -1, -1, -1, 30 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 1, 3, 4, 5, 6, 7, 8, 28, 29, 30, 31, 34, 37, 46, 15, 8, 8, 8, 8, 8, 20, 21, 22, 24, 40, 41, 42, 0, 28, 14, 18, 8, 16, 41, 8, 9, 43, 45, 25, 8, 21, 8, 34, 11, 12, 13, 35, 38, 39, 15, 8, 32, 23, 17, 44, 8, 19, 17, 36, 8, 17, 33, 15, 45, 26, 15, 38, 8, 9, 10, 40, 8, 44, 8, 36, 41, 8, 9, 10, 33 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) yytype_int16 *bottom; yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); fprintf (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss = yyssa; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 4: #line 106 "mwrap.y" { (yyvsp[(3) - (3)].func)->ret = (yyvsp[(1) - (3)].var); (yyvsp[(3) - (3)].func)->id = ++func_id; type_errs += typecheck((yyvsp[(3) - (3)].func), linenum); if (outfp) print_matlab_call(outfp, (yyvsp[(3) - (3)].func), mexfunc); add_func((yyvsp[(3) - (3)].func)); ;} break; case 5: #line 114 "mwrap.y" { (yyvsp[(1) - (1)].func)->id = ++func_id; type_errs += typecheck((yyvsp[(1) - (1)].func), linenum); if (outfp) print_matlab_call(outfp, (yyvsp[(1) - (1)].func), mexfunc); add_func((yyvsp[(1) - (1)].func)); ;} break; case 9: #line 124 "mwrap.y" { yyerrok; ;} break; case 10: #line 127 "mwrap.y" { if (strcmp((yyvsp[(2) - (4)].string), "numeric") == 0) { add_scalar_type((yyvsp[(3) - (4)].string)); } else if (strcmp((yyvsp[(2) - (4)].string), "dcomplex") == 0) { add_zscalar_type((yyvsp[(3) - (4)].string)); } else if (strcmp((yyvsp[(2) - (4)].string), "fcomplex") == 0) { add_cscalar_type((yyvsp[(3) - (4)].string)); } else if (strcmp((yyvsp[(2) - (4)].string), "mxArray") == 0) { add_mxarray_type((yyvsp[(3) - (4)].string)); } else { fprintf(stderr, "Unrecognized typespace: %s\n", (yyvsp[(2) - (4)].string)); ++type_errs; } delete[] (yyvsp[(2) - (4)].string); delete[] (yyvsp[(3) - (4)].string); ;} break; case 11: #line 145 "mwrap.y" { add_inherits((yyvsp[(2) - (5)].string), (yyvsp[(4) - (5)].inherits)); delete[] (yyvsp[(2) - (5)].string); destroy((yyvsp[(4) - (5)].inherits)); ;} break; case 12: #line 152 "mwrap.y" { (yyval.inherits) = new InheritsDecl((yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].inherits)); ;} break; case 13: #line 155 "mwrap.y" { (yyval.inherits) = new InheritsDecl((yyvsp[(2) - (3)].string), (yyvsp[(3) - (3)].inherits)); ;} break; case 14: #line 156 "mwrap.y" { (yyval.inherits) = NULL; ;} break; case 15: #line 158 "mwrap.y" { (yyval.func) = (yyvsp[(1) - (5)].func); (yyval.func)->args = (yyvsp[(3) - (5)].var); ;} break; case 16: #line 161 "mwrap.y" { (yyval.var) = (yyvsp[(1) - (2)].var); (yyval.var)->next = (yyvsp[(2) - (2)].var); ;} break; case 17: #line 162 "mwrap.y" { (yyval.var) = NULL; ;} break; case 18: #line 165 "mwrap.y" {(yyval.var) = (yyvsp[(2) - (3)].var); (yyval.var)->next = (yyvsp[(3) - (3)].var); ;} break; case 19: #line 166 "mwrap.y" { (yyval.var) = NULL; ;} break; case 20: #line 168 "mwrap.y" { (yyval.var) = new Var('o', (yyvsp[(1) - (2)].string), NULL, (yyvsp[(2) - (2)].string)); ;} break; case 21: #line 169 "mwrap.y" { (yyval.var) = new Var('o', (yyvsp[(1) - (3)].string), (yyvsp[(2) - (3)].qual), (yyvsp[(3) - (3)].string)); ;} break; case 22: #line 170 "mwrap.y" { (yyval.var) = new Var('o', (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].qual), (yyvsp[(2) - (3)].string)); ;} break; case 23: #line 172 "mwrap.y" { (yyval.var) = new Var((yyvsp[(1) - (3)].c), (yyvsp[(2) - (3)].string), NULL, (yyvsp[(3) - (3)].string)); ;} break; case 24: #line 173 "mwrap.y" { (yyval.var) = new Var((yyvsp[(1) - (4)].c), (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].qual), (yyvsp[(4) - (4)].string)); ;} break; case 25: #line 174 "mwrap.y" { (yyval.var) = new Var((yyvsp[(1) - (4)].c), (yyvsp[(2) - (4)].string), (yyvsp[(4) - (4)].qual), (yyvsp[(3) - (4)].string)); ;} break; case 26: #line 176 "mwrap.y" { (yyval.var) = new Var((yyvsp[(1) - (3)].c), (yyvsp[(2) - (3)].string), NULL, (yyvsp[(3) - (3)].string)); ;} break; case 27: #line 177 "mwrap.y" { (yyval.var) = new Var((yyvsp[(1) - (4)].c), (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].qual), (yyvsp[(4) - (4)].string)); ;} break; case 28: #line 179 "mwrap.y" { (yyval.var) = new Var((yyvsp[(1) - (3)].c), (yyvsp[(2) - (3)].string), NULL, (yyvsp[(3) - (3)].string)); ;} break; case 29: #line 180 "mwrap.y" { (yyval.var) = new Var((yyvsp[(1) - (4)].c), (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].qual), (yyvsp[(4) - (4)].string)); ;} break; case 30: #line 183 "mwrap.y" { (yyval.c) = 'i'; ;} break; case 31: #line 184 "mwrap.y" { (yyval.c) = 'o'; ;} break; case 32: #line 185 "mwrap.y" { (yyval.c) = 'b'; ;} break; case 33: #line 186 "mwrap.y" { (yyval.c) = 'i'; ;} break; case 34: #line 189 "mwrap.y" { (yyval.qual) = new TypeQual('*', NULL); ;} break; case 35: #line 190 "mwrap.y" { (yyval.qual) = new TypeQual('&', NULL); ;} break; case 36: #line 191 "mwrap.y" { (yyval.qual) = (yyvsp[(1) - (1)].qual); ;} break; case 37: #line 194 "mwrap.y" { (yyval.qual) = new TypeQual('a', (yyvsp[(1) - (1)].expr)); ;} break; case 38: #line 195 "mwrap.y" { (yyval.qual) = new TypeQual('r', (yyvsp[(1) - (2)].expr)); ;} break; case 39: #line 197 "mwrap.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} break; case 40: #line 200 "mwrap.y" { (yyval.expr) = (yyvsp[(1) - (2)].expr); (yyval.expr)->next = (yyvsp[(2) - (2)].expr); ;} break; case 41: #line 201 "mwrap.y" { (yyval.expr) = NULL; ;} break; case 42: #line 204 "mwrap.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); (yyval.expr)->next = (yyvsp[(3) - (3)].expr); ;} break; case 43: #line 205 "mwrap.y" { (yyval.expr) = NULL; ;} break; case 44: #line 208 "mwrap.y" { (yyval.expr) = new Expr((yyvsp[(1) - (1)].string)); ;} break; case 45: #line 209 "mwrap.y" { (yyval.expr) = new Expr((yyvsp[(1) - (1)].string)); ;} break; case 46: #line 212 "mwrap.y" { (yyval.func) = new Func((yyvsp[(1) - (6)].string), (yyvsp[(4) - (6)].string), (yyvsp[(6) - (6)].string), current_ifname, linenum); ;} break; case 47: #line 213 "mwrap.y" { (yyval.func) = new Func(NULL, NULL, (yyvsp[(1) - (1)].string), current_ifname, linenum); ;} break; case 48: #line 214 "mwrap.y" { (yyval.func) = new Func(NULL, NULL, (yyvsp[(2) - (2)].string), current_ifname, linenum); (yyval.func)->fort = true; ;} break; case 49: #line 217 "mwrap.y" { (yyval.func) = new Func(NULL, (yyvsp[(2) - (2)].string), mwrap_strdup("new"), current_ifname, linenum); ;} break; /* Line 1267 of yacc.c. */ #line 1729 "mwrap.cc" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } #line 222 "mwrap.y" #include #include extern FILE* yyin; int yywrap() { return 1; } int yyerror(char* s) { fprintf(stderr, "Parse error (%s:%d): %s\n", current_ifname.c_str(), linenum, s); } char* mwrap_strdup(const char* s) { char* result = new char[strlen(s)+1]; strcpy(result, s); return result; } const char* help_string = "Syntax:\n" " mwrap [-mex outputmex] [-m output.m] [-c outputmex.c] [-mb]\n" " [-list] [-catch] 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" " -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, 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], "-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], "-c99complex") == 0 || strcmp(argv[j], "-cppcomplex") == 0); else { linenum = 1; type_errs = 0; yyin = fopen(argv[j], "r"); if (yyin) { current_ifname = argv[j]; 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-0.33/src/mwrap.hh0000600001174600117460000000523011133213550014605 0ustar dbindeldbindel/* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { NON_C_LINE = 258, NEW = 259, TYPEDEF = 260, CLASS = 261, FORTRAN = 262, ID = 263, NUMBER = 264, STRING = 265, INPUT = 266, OUTPUT = 267, INOUT = 268 }; #endif /* Tokens. */ #define NON_C_LINE 258 #define NEW 259 #define TYPEDEF 260 #define CLASS 261 #define FORTRAN 262 #define ID 263 #define NUMBER 264 #define STRING 265 #define INPUT 266 #define OUTPUT 267 #define INOUT 268 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE #line 77 "mwrap.y" { char* string; struct Func* func; struct Var* var; struct TypeQual* qual; struct Expr* expr; struct InheritsDecl* inherits; char c; } /* Line 1529 of yacc.c. */ #line 85 "mwrap.hh" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; mwrap-0.33/src/mwrap.l0000600001174600117460000001450711133213513014447 0ustar dbindeldbindel%{ /* * 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-0.33/src/mwrap.y0000600001174600117460000002165111133213513014462 0ustar dbindeldbindel%{ /* * 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(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 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 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', $1, NULL, $2); } basevar: ID quals ID { $$ = new Var('o', $1, $2, $3); } basevar: ID ID aqual { $$ = new Var('o', $1, $3, $2); } var: iospec ID ID { $$ = new Var($1, $2, NULL, $3); } var: iospec ID quals ID { $$ = new Var($1, $2, $3, $4); } var: iospec ID ID aqual { $$ = new Var($1, $2, $4, $3); } var: iospec ID NUMBER { $$ = new Var($1, $2, NULL, $3); } var: iospec ID quals NUMBER { $$ = new Var($1, $2, $3, $4); } var: iospec ID STRING { $$ = new Var($1, $2, NULL, $3); } var: iospec ID quals STRING { $$ = new Var($1, $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(char* s) { fprintf(stderr, "Parse error (%s:%d): %s\n", current_ifname.c_str(), linenum, s); } char* mwrap_strdup(const char* s) { char* result = new char[strlen(s)+1]; strcpy(result, s); return result; } const char* help_string = "Syntax:\n" " mwrap [-mex outputmex] [-m output.m] [-c outputmex.c] [-mb]\n" " [-list] [-catch] 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" " -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, 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], "-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], "-c99complex") == 0 || strcmp(argv[j], "-cppcomplex") == 0); else { linenum = 1; type_errs = 0; yyin = fopen(argv[j], "r"); if (yyin) { current_ifname = argv[j]; 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-0.33/src/stringify.c0000600001174600117460000000173111133213514015322 0ustar dbindeldbindel/* * 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-0.33/testing/Makefile0000600001174600117460000000346711153600446015504 0ustar dbindeldbindelinclude ../make.inc all: test_transfers test_cpp_complex $(TESTC99COMPLEX) test_syntax \ test_typecheck test_catch test_fortran1 test_fortran2 \ test_redirect test_include 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 test_syntax: - ../mwrap -cppcomplex test_syntax.mw >& test_syntax.log diff test_syntax.log test_syntax.ref test_typecheck: - ../mwrap -cppcomplex test_typecheck.mw >& 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 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 mwrap-0.33/testing/test_all.m0000600001174600117460000000023711153600515016016 0ustar dbindeldbindeltest_transfers; test_cpp_complex; if exist('test_c99_complex.m'), test_c99_complex; end test_catch; test_fortran1; test_fortran2; test_redirect; test_include; mwrap-0.33/testing/test_c99_complex.mw0000600001174600117460000000112011153600317017560 0ustar dbindeldbindelfunction 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-0.33/testing/test_catch.mw0000600001174600117460000000030211133213514016505 0ustar dbindeldbindelfunction test_catch $ void toss() $ { $ throw("Cookies"); $ } try # toss(); disp('Failed to properly catch exception'); catch fprintf('Correctly caught message: %s\n', lasterr); end mwrap-0.33/testing/test_cpp_complex.mw0000600001174600117460000000115611133213514017744 0ustar dbindeldbindelfunction 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-0.33/testing/test_fortran1.mw0000600001174600117460000000043611153573101017172 0ustar dbindeldbindelfunction test_fortran1 $ #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-0.33/testing/test_fortran2.mw0000600001174600117460000000043611153573110017173 0ustar dbindeldbindelfunction 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-0.33/testing/test_include.mw0000600001174600117460000000034211133213514017052 0ustar dbindeldbindelfunction test_include() @include test_include2.mw tassert(j == 4, 'Include test'); % ================================================================ function tassert(pred, msg) if ~pred, fprintf('Failure: %s\n', msg); end mwrap-0.33/testing/test_include2.mw0000600001174600117460000000007011133213514017132 0ustar dbindeldbindel$int add2(int i) { return i+2; } # int j = add2(int 2); mwrap-0.33/testing/test_redirect.mw0000600001174600117460000000021111133213514017223 0ustar dbindeldbindel@function test_redirect if test_redirect1(42) ~= 42, fprint('Failure: Redirection failed?'); end @function x = test_redirect1(y) x = y; mwrap-0.33/testing/test_syntax.mw0000600001174600117460000000030711133213514016756 0ustar dbindeldbindel 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-0.33/testing/test_syntax.ref0000600001174600117460000000024011133213514017103 0ustar dbindeldbindelParse error (test_syntax.mw:4): syntax error, unexpected NON_C_LINE, expecting ';' Parse error (test_syntax.mw:8): syntax error, unexpected $end, expecting ';' mwrap-0.33/testing/test_transfers.mw0000600001174600117460000003603511153572757017471 0ustar dbindeldbindelfunction 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) $] % ================================================================ 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; # typedef numeric byte; # takes_double(double& x); # takes_float(float& x); # 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-0.33/testing/test_typecheck.mw0000600001174600117460000000123711133213514017412 0ustar dbindeldbindel 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-0.33/testing/test_typecheck.ref0000600001174600117460000000117611133213514017545 0ustar dbindeldbindelError (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